/*-< POSIXSEM.H >---------------------------------------------------*--------*/ /* SHMEM Version 1.0 (c) 1998 GARRET * ? */ /* (Shared Memory Manager) * /\| */ /* * / \ */ /* Created: 2-Apr-98 K.A. Knizhnik * / [] \ */ /* Last update: 12-Apr-98 K.A. Knizhnik * GARRET */ /*------------------------------------------------------------------*--------*/ /* Posix semaphores interface * */ /*------------------------------------------------------------------*--------*/ #ifndef __POSIXSEM_H__ #define __POSIXSEM_H__ #include #ifdef __cplusplus extern "C" { #endif #define items(x) (sizeof(x)/sizeof(*x)) typedef int sem_t; extern int sem_init(sem_t* sem, char* name, unsigned init_value); extern int sem_open(sem_t* sem, char* name); extern int sem_wait(sem_t* sem); extern int sem_trywait(sem_t* sem); extern int sem_post(sem_t* sem); extern int sem_destroy(sem_t* sem); typedef struct { int count; int key; } msem_data; typedef struct { msem_data* data; sem_t id; } msem_t; extern int msem_init(msem_t* sem, msem_data* data); extern int msem_open(msem_t* sem, msem_data* data); extern int msem_destroy(msem_t* sem); /* * Make sure gcc doesn't try to be clever and move things around * on us. We need to use _exactly_ the address the user gave us, * not some alias that contains the same information. */ #define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x) static __inline__ int msem_lock(msem_t* sem) { int inc = 1; int* p = &sem->data->count; __asm__ __volatile__( "lock; xadd %0,%1" :"=r" (inc), "=m" (__atomic_fool_gcc(p)) :"r" (inc), "m" (__atomic_fool_gcc(p))); if (inc != 0) { return sem_wait(&sem->id); } return 0; } static __inline__ int msem_trylock(msem_t* sem) { int lock = 1; int res = 0; int* p = &sem->data->count; __asm__ __volatile__( "lock; cmpxchg %3,%1" : "=a" (res), "=m" (__atomic_fool_gcc(p)) :"a" (res), "d" (lock), "m" (__atomic_fool_gcc(p)) :"ax"); if (res != 0) { errno = EAGAIN; return -1; } return 0; } static __inline__ int msem_unlock(msem_t* sem) { int inc = -1; int* p = &sem->data->count; __asm__ __volatile__( "lock; xadd %0,%1" :"=d" (inc), "=m" (__atomic_fool_gcc(p)) :"d" (inc), "m" (__atomic_fool_gcc(p))); if (inc != 1) { /* some other processes waiting to enter critical section */ return sem_post(&sem->id); } return 0; } #ifdef __cplusplus } #endif #endif