sema.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:5k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: sema.c,v 1.20.4.1 1998/07/19 22:49:56 wlu Exp $
  8.  */
  9. #include "socks5p.h"
  10. #include "sema.h"
  11. #include "log.h"
  12. #ifdef USE_SYSTEM_SEMAPHORE
  13. #ifdef HAVE_SYS_IPC_H
  14. #include <sys/ipc.h>
  15. #endif
  16. #ifdef HAVE_SYS_SEM_H
  17. #include <sys/sem.h>
  18. #endif
  19. int semacquire(void *sem) {
  20.     struct sembuf sb = { 0, -1, SEM_UNDO };
  21.     if (sem && semop(*(int *)sem, &sb, 1) < 0) {
  22. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semacquire: semop failed: %m");
  23. return -1;
  24.     }
  25.     return 0;
  26. }
  27. int semrelease(void *sem) {
  28.     struct sembuf sb = { 0, 1, SEM_UNDO };
  29.     if (sem && semop(*(int *)sem, &sb, 1) < 0) {
  30. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semrelease: semop failed: %m");
  31. return -1;
  32.     }
  33.     return 0;
  34. }
  35. int semreset(void *sem, int val) {
  36.     /* I think semaphores with UNDO won't need resetting...                  */
  37.     return 0;
  38. }
  39. void semdestroy(void *sem) {
  40.     union { int val; struct semid_ds *buf; u_short *array; } u;
  41.     u.val = 1;
  42.     semctl(*(int *)sem, 0, IPC_RMID, u);
  43. }
  44. void *semcreate(int val) {
  45.     int *semid = (int *)malloc(sizeof(int));
  46.     union { int val; struct semid_ds *buf; u_short *array; } u;
  47.     u.val = val;
  48.     if (semid == NULL) {
  49. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: malloc failed");
  50. return NULL;
  51.     }
  52.     if ((*semid = semget(IPC_PRIVATE, 1, 0666)) < 0) {
  53. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: semget failed: %m");
  54. return NULL;
  55.     }
  56.     if (semctl(*semid, 0, SETVAL, u) < 0) {
  57. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: semctl failed: %m");
  58. return NULL;
  59.     }
  60.     return (void *)semid;
  61. }
  62. #elif defined(USE_SEMAPHORES)
  63. #ifdef HAVE_SYS_IOCTL_H
  64. #include <sys/ioctl.h>
  65. #endif
  66. #ifdef HAVE_SYS_FILIO_H
  67. #include <sys/filio.h>
  68. #endif
  69. static int semstart(S5IOHandle *fd, int count) {
  70.     if (pipe(fd) < 0) {
  71. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semstart: pipe failed: %m");
  72. return -1;
  73.     }
  74.     
  75.     while (count-- > 0) semrelease((void *)fd);
  76.     return 0;
  77. }
  78. /* Lock (using the semaphore pipe, semfd) control of the signaling and pipes */
  79. /* (pipe reads and writes are atomic, so the pipe can act as a semaphore.)   */
  80. int semacquire(void *sem) {
  81.     S5IOHandle *fd = (int *)sem;
  82.     char c;
  83.     if (sem && RECVSOCKET(fd[0], &c, 1, 0) < 0) {
  84. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semacquire: read failed: %m");
  85. return -1;
  86.     }
  87.     return 0;
  88. }
  89. /* Unlock (using the semaphore pipe) control of the signaling and pipes      */
  90. /* (pipe reads and writes are atomic, so the pipe can act as a semaphore.)   */
  91. int semrelease(void *sem) {
  92.     S5IOHandle *fd = (int *)sem;
  93.     if (sem && SENDSOCKET(fd[1], " ", 1, 0) != 1) {
  94. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semrelease: write failed: %m");
  95. return -1;
  96.     }
  97.     return 0;
  98. }
  99. int semreset(void *sem, int val) {
  100.     S5IOHandle *fd = (int *)sem;
  101.     int nq;
  102.     /* ok? */
  103.     if (sem == NULL) return 0;
  104. #ifdef FIONREAD
  105.     ioctl(fd[0], FIONREAD, (char *)&nq);
  106.     if (nq == val) return 0;
  107. #else
  108.     /* on some OSs fstat works on pipes, if it doesn't, it will return -1,   */
  109.     /* and we'll be ok.                                                      */
  110.     {
  111.       struct stat sb;
  112.       if (fstat(fd[0], &sb) == 0 && sb.st_size == val) return 0;
  113.     }
  114. #endif
  115.     /* Need to reset it, really...                                           */
  116.     close(fd[0]);
  117.     close(fd[1]);
  118.     return semstart((int *)sem, val);
  119.     /* Since this only gets called on HUPs, we can deal with recreating the  */
  120.     /* pipe -- It doesn't happen that often, and the old pipe should be      */
  121.     /* gone or will be as soon as the last child that has it open exits.     */
  122.     /* while (nq-- > val) semacquire(sem); while (nq++ < val)                */
  123.     /* semrelease(sem);                                                      */
  124. }
  125. void semdestroy(void *sem) {
  126.     S5IOHandle *fd = (int *)sem;
  127.     if (!sem) return;
  128.     close(fd[0]);
  129.     close(fd[1]);
  130.     free(sem);
  131. }
  132. void *semcreate(int count) {
  133.     S5IOHandle *fd;
  134.     if ((fd  = (int *)malloc(2 * sizeof(int)))== NULL) {
  135. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "Semcreate: malloc failed");
  136. return NULL;
  137.     }
  138.     semstart(fd, count);
  139.     return (void *)fd;
  140. }
  141. #endif /* not __svr4__ */