github.com/afumu/libc@v0.0.6/musl/src/ipc/semctl.c (about) 1 #include <sys/sem.h> 2 #include <stdarg.h> 3 #include <endian.h> 4 #include "syscall.h" 5 #include "ipc.h" 6 7 #if __BYTE_ORDER != __BIG_ENDIAN 8 #undef SYSCALL_IPC_BROKEN_MODE 9 #endif 10 11 union semun { 12 int val; 13 struct semid_ds *buf; 14 unsigned short *array; 15 }; 16 17 int semctl(int id, int num, int cmd, ...) 18 { 19 union semun arg = {0}; 20 va_list ap; 21 switch (cmd & ~IPC_TIME64) { 22 case SETVAL: case GETALL: case SETALL: case IPC_SET: 23 case IPC_INFO: case SEM_INFO: 24 case IPC_STAT & ~IPC_TIME64: 25 case SEM_STAT & ~IPC_TIME64: 26 case SEM_STAT_ANY & ~IPC_TIME64: 27 va_start(ap, cmd); 28 arg = va_arg(ap, union semun); 29 va_end(ap); 30 } 31 #if IPC_TIME64 32 struct semid_ds out, *orig; 33 if (cmd&IPC_TIME64) { 34 out = (struct semid_ds){0}; 35 orig = arg.buf; 36 arg.buf = &out; 37 } 38 #endif 39 #ifdef SYSCALL_IPC_BROKEN_MODE 40 struct semid_ds tmp; 41 if (cmd == IPC_SET) { 42 tmp = *arg.buf; 43 tmp.sem_perm.mode *= 0x10000U; 44 arg.buf = &tmp; 45 } 46 #endif 47 #ifndef SYS_ipc 48 int r = __syscall(SYS_semctl, id, num, IPC_CMD(cmd), arg.buf); 49 #else 50 int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, IPC_CMD(cmd), &arg.buf); 51 #endif 52 #ifdef SYSCALL_IPC_BROKEN_MODE 53 if (r >= 0) switch (cmd | IPC_TIME64) { 54 case IPC_STAT: 55 case SEM_STAT: 56 case SEM_STAT_ANY: 57 arg.buf->sem_perm.mode >>= 16; 58 } 59 #endif 60 #if IPC_TIME64 61 if (r >= 0 && (cmd&IPC_TIME64)) { 62 arg.buf = orig; 63 *arg.buf = out; 64 IPC_HILO(arg.buf, sem_otime); 65 IPC_HILO(arg.buf, sem_ctime); 66 } 67 #endif 68 return __syscall_ret(r); 69 }