|
|
|
@ -13,11 +13,14 @@ |
|
|
|
|
|
|
|
|
|
#include <errno.h> |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
typedef struct |
|
|
|
|
{ |
|
|
|
|
int m_numSems; |
|
|
|
|
off_t m_semaphoreHandles; // offset from beginning of header
|
|
|
|
|
off_t m_semaphoreCounts; // offset from beginning of header
|
|
|
|
|
} win32_sem_set_hdr; |
|
|
|
|
off_t m_semaphoreHandles; |
|
|
|
|
//offset from beginning of header
|
|
|
|
|
off_t m_semaphoreCounts; |
|
|
|
|
//offset from beginning of header
|
|
|
|
|
} win32_sem_set_hdr; |
|
|
|
|
|
|
|
|
|
/* Control of a semaphore pool. The pool is an area in which we stored all
|
|
|
|
|
** the semIds of the pool. The first long is the number of semaphore |
|
|
|
@ -27,22 +30,24 @@ typedef struct { |
|
|
|
|
int |
|
|
|
|
semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
{ |
|
|
|
|
win32_sem_set_hdr* the_set = (win32_sem_set_hdr*)MAKE_PTR(semId); |
|
|
|
|
win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId); |
|
|
|
|
|
|
|
|
|
/* semNum might be 0 */ |
|
|
|
|
/* semun.array contains the sem initial values */ |
|
|
|
|
int* sem_counts = (int*)((off_t)the_set + the_set->m_semaphoreCounts); |
|
|
|
|
int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts); |
|
|
|
|
|
|
|
|
|
/* Fix the count of all sem of the pool to semun.array */ |
|
|
|
|
if (flag == SETALL) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
int i; |
|
|
|
|
struct sembuf sops; |
|
|
|
|
|
|
|
|
|
sops.sem_flg = IPC_NOWAIT; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < the_set->m_numSems; ++i) { |
|
|
|
|
for (i = 0; i < the_set->m_numSems; ++i) |
|
|
|
|
{ |
|
|
|
|
if (semun.array[i] == sem_counts[i]) |
|
|
|
|
continue; /* Nothing to do */ |
|
|
|
|
continue; /* Nothing to do */ |
|
|
|
|
|
|
|
|
|
if (semun.array[i] < sem_counts[i]) |
|
|
|
|
sops.sem_op = -1; |
|
|
|
@ -50,7 +55,7 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
sops.sem_op = 1; |
|
|
|
|
|
|
|
|
|
sops.sem_num = i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Quickly lock/unlock the semaphore (if we can) */ |
|
|
|
|
if (semop(semId, &sops, 1) < 0) |
|
|
|
|
return -1; |
|
|
|
@ -61,8 +66,10 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
/* Fix the count of one semaphore to semun.val */ |
|
|
|
|
else if (flag == SETVAL) |
|
|
|
|
{ |
|
|
|
|
if (semun.val != sem_counts[semNum]) { |
|
|
|
|
if (semun.val != sem_counts[semNum]) |
|
|
|
|
{ |
|
|
|
|
struct sembuf sops; |
|
|
|
|
|
|
|
|
|
sops.sem_flg = IPC_NOWAIT; |
|
|
|
|
sops.sem_num = semNum; |
|
|
|
|
|
|
|
|
@ -70,7 +77,7 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
sops.sem_op = -1; |
|
|
|
|
else |
|
|
|
|
sops.sem_op = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Quickly lock/unlock the semaphore (if we can) */ |
|
|
|
|
if (semop(semId, &sops, 1) < 0) |
|
|
|
|
return -1; |
|
|
|
@ -82,8 +89,8 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
/* Delete the pool */ |
|
|
|
|
else if (flag == IPC_RMID) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
HANDLE* sem_handles = (HANDLE*)((off_t)the_set + the_set->m_semaphoreHandles); |
|
|
|
|
int i; |
|
|
|
|
HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles); |
|
|
|
|
|
|
|
|
|
/* Loop over all semaphore to delete them */ |
|
|
|
|
for (i = 0; i < the_set->m_numSems; ++i) |
|
|
|
@ -94,15 +101,11 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
|
|
|
|
|
/* Get the current semaphore count */ |
|
|
|
|
else if (flag == GETNCNT) |
|
|
|
|
{ |
|
|
|
|
return the_set->m_numSems; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Get the current semaphore count of the first semaphore in the pool */ |
|
|
|
|
else if (flag == GETVAL) |
|
|
|
|
{ |
|
|
|
|
return sem_counts[semNum]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Other commands not yet supported */ |
|
|
|
|
else |
|
|
|
@ -116,17 +119,17 @@ semctl(int semId, int semNum, int flag, union semun semun) |
|
|
|
|
int |
|
|
|
|
semget(int semKey, int semNum, int flags) |
|
|
|
|
{ |
|
|
|
|
char semname[32]; |
|
|
|
|
char cur_num[20]; |
|
|
|
|
DWORD last_error; |
|
|
|
|
char* num_part; |
|
|
|
|
bool ans = true; |
|
|
|
|
char semname[32]; |
|
|
|
|
char cur_num[20]; |
|
|
|
|
DWORD last_error; |
|
|
|
|
char *num_part; |
|
|
|
|
bool ans = true; |
|
|
|
|
SECURITY_ATTRIBUTES sec_attrs; |
|
|
|
|
HANDLE cur_handle; |
|
|
|
|
bool found = false; |
|
|
|
|
Size sem_set_size = sizeof(win32_sem_set_hdr) + semNum * (sizeof(HANDLE) + sizeof(int)); |
|
|
|
|
HANDLE* sem_handles = NULL; |
|
|
|
|
int* sem_counts = NULL; |
|
|
|
|
HANDLE cur_handle; |
|
|
|
|
bool found = false; |
|
|
|
|
Size sem_set_size = sizeof(win32_sem_set_hdr) + semNum * (sizeof(HANDLE) + sizeof(int)); |
|
|
|
|
HANDLE *sem_handles = NULL; |
|
|
|
|
int *sem_counts = NULL; |
|
|
|
|
|
|
|
|
|
sec_attrs.nLength = sizeof(sec_attrs); |
|
|
|
|
sec_attrs.lpSecurityDescriptor = NULL; |
|
|
|
@ -135,23 +138,27 @@ semget(int semKey, int semNum, int flags) |
|
|
|
|
sprintf(semname, "PG_SEMSET.%d.", semKey); |
|
|
|
|
num_part = semname + strlen(semname); |
|
|
|
|
|
|
|
|
|
strcpy(num_part, _itoa(_getpid() * -1, cur_num, 10)); /* For shared memory, include the pid */ |
|
|
|
|
win32_sem_set_hdr* new_set = (win32_sem_set_hdr*)ShmemInitStruct(semname, sem_set_size, &found); |
|
|
|
|
strcpy(num_part, _itoa(_getpid() * -1, cur_num, 10)); /* For shared memory,
|
|
|
|
|
* include the pid */ |
|
|
|
|
win32_sem_set_hdr *new_set = (win32_sem_set_hdr *) ShmemInitStruct(semname, sem_set_size, &found); |
|
|
|
|
|
|
|
|
|
if (found) { |
|
|
|
|
if (found) |
|
|
|
|
{ |
|
|
|
|
/* This should *never* happen */ |
|
|
|
|
errno = EEXIST; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
new_set->m_numSems = semNum; |
|
|
|
|
new_set->m_semaphoreHandles = sizeof(win32_sem_set_hdr); // array starts after header
|
|
|
|
|
new_set->m_semaphoreCounts = new_set->m_semaphoreHandles + (sizeof(HANDLE) * semNum); |
|
|
|
|
new_set->m_semaphoreHandles = sizeof(win32_sem_set_hdr); |
|
|
|
|
//array starts after header
|
|
|
|
|
new_set->m_semaphoreCounts = new_set->m_semaphoreHandles + (sizeof(HANDLE) * semNum); |
|
|
|
|
|
|
|
|
|
sem_handles = (HANDLE*)((off_t)new_set + new_set->m_semaphoreHandles); |
|
|
|
|
sem_counts = (int*)((off_t)new_set + new_set->m_semaphoreCounts); |
|
|
|
|
sem_handles = (HANDLE *) ((off_t) new_set + new_set->m_semaphoreHandles); |
|
|
|
|
sem_counts = (int *) ((off_t) new_set + new_set->m_semaphoreCounts); |
|
|
|
|
|
|
|
|
|
for (int i=0; i<semNum && ans; ++i) { |
|
|
|
|
for (int i = 0; i < semNum && ans; ++i) |
|
|
|
|
{ |
|
|
|
|
strcpy(num_part, _itoa(i, cur_num, 10)); |
|
|
|
|
|
|
|
|
|
if (flags & IPC_CREAT) |
|
|
|
@ -174,11 +181,13 @@ semget(int semKey, int semNum, int flags) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ans) { |
|
|
|
|
if (ans) |
|
|
|
|
return MAKE_OFFSET(new_set); |
|
|
|
|
} else { |
|
|
|
|
// Blow away what we've got right now...
|
|
|
|
|
for (int i=0; i<semNum; ++i) { |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* Blow away what we've got right now... */ |
|
|
|
|
for (int i = 0; i < semNum; ++i) |
|
|
|
|
{ |
|
|
|
|
if (sem_handles[i]) |
|
|
|
|
CloseHandle(sem_handles[i]); |
|
|
|
|
else |
|
|
|
@ -193,13 +202,17 @@ semget(int semKey, int semNum, int flags) |
|
|
|
|
int |
|
|
|
|
semop(int semId, struct sembuf * sops, int nsops) |
|
|
|
|
{ |
|
|
|
|
win32_sem_set_hdr* the_set = (win32_sem_set_hdr*)MAKE_PTR(semId); |
|
|
|
|
HANDLE* sem_handles = (HANDLE*)((off_t)the_set + the_set->m_semaphoreHandles); |
|
|
|
|
int* sem_counts = (int*)((off_t)the_set + the_set->m_semaphoreCounts); |
|
|
|
|
HANDLE cur_handle; |
|
|
|
|
win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId); |
|
|
|
|
HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles); |
|
|
|
|
int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts); |
|
|
|
|
HANDLE cur_handle; |
|
|
|
|
|
|
|
|
|
if (nsops != 1) { |
|
|
|
|
/* Not supported (we return on 1st success, and don't cancel earlier ops) */ |
|
|
|
|
if (nsops != 1) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Not supported (we return on 1st success, and don't cancel |
|
|
|
|
* earlier ops) |
|
|
|
|
*/ |
|
|
|
|
errno = E2BIG; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
@ -208,23 +221,27 @@ semop(int semId, struct sembuf * sops, int nsops) |
|
|
|
|
|
|
|
|
|
if (sops[0].sem_op == -1) |
|
|
|
|
{ |
|
|
|
|
DWORD ret; |
|
|
|
|
DWORD ret; |
|
|
|
|
|
|
|
|
|
if (sops[0].sem_flg & IPC_NOWAIT) |
|
|
|
|
ret = WaitForSingleObject(cur_handle, 0); |
|
|
|
|
else |
|
|
|
|
ret = WaitForSingleObject(cur_handle, INFINITE); |
|
|
|
|
|
|
|
|
|
if (ret == WAIT_OBJECT_0) { |
|
|
|
|
if (ret == WAIT_OBJECT_0) |
|
|
|
|
{ |
|
|
|
|
/* We got it! */ |
|
|
|
|
sem_counts[sops[0].sem_num]--; |
|
|
|
|
return 0; |
|
|
|
|
} else if (ret == WAIT_TIMEOUT) |
|
|
|
|
} |
|
|
|
|
else if (ret == WAIT_TIMEOUT) |
|
|
|
|
/* Couldn't get it */ |
|
|
|
|
errno = EAGAIN; |
|
|
|
|
else |
|
|
|
|
errno = EIDRM; |
|
|
|
|
} |
|
|
|
|
else if (sops[0].sem_op > 0) { |
|
|
|
|
else if (sops[0].sem_op > 0) |
|
|
|
|
{ |
|
|
|
|
/* Don't want the lock anymore */ |
|
|
|
|
sem_counts[sops[0].sem_num]++; |
|
|
|
|
ReleaseSemaphore(cur_handle, sops[0].sem_op, NULL); |
|
|
|
|