semctl.c 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. #include <sys/sem.h>
  2. #include <stdarg.h>
  3. #include <endian.h>
  4. #include "syscall.h"
  5. #include "ipc.h"
  6. #if __BYTE_ORDER != __BIG_ENDIAN
  7. #undef SYSCALL_IPC_BROKEN_MODE
  8. #endif
  9. union semun {
  10. int val;
  11. struct semid_ds *buf;
  12. unsigned short *array;
  13. };
  14. int semctl(int id, int num, int cmd, ...)
  15. {
  16. union semun arg = {0};
  17. va_list ap;
  18. switch (cmd) {
  19. case SETVAL: case GETALL: case SETALL: case IPC_STAT: case IPC_SET:
  20. case IPC_INFO: case SEM_INFO: case SEM_STAT: case SEM_STAT_ANY:
  21. va_start(ap, cmd);
  22. arg = va_arg(ap, union semun);
  23. va_end(ap);
  24. }
  25. #ifdef SYSCALL_IPC_BROKEN_MODE
  26. struct semid_ds tmp;
  27. if (cmd == IPC_SET) {
  28. tmp = *arg.buf;
  29. tmp.sem_perm.mode *= 0x10000U;
  30. arg.buf = &tmp;
  31. }
  32. #endif
  33. #ifndef SYS_ipc
  34. int r = __syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf);
  35. #else
  36. int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf);
  37. #endif
  38. #ifdef SYSCALL_IPC_BROKEN_MODE
  39. if (r >= 0) switch (cmd) {
  40. case IPC_STAT:
  41. case SEM_STAT:
  42. case SEM_STAT_ANY:
  43. arg.buf->sem_perm.mode >>= 16;
  44. }
  45. #endif
  46. return __syscall_ret(r);
  47. }