fsmutex.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /*
  13. * fsmutex: Mutexes that are filesystem-based so they're available from more
  14. * than one process and address space
  15. *
  16. * Rob McCool
  17. */
  18. #include "base/fsmutex.h"
  19. #ifdef THREAD_ANY
  20. #include "base/crit.h"
  21. #include "base/systhr.h"
  22. #endif
  23. #include "base/util.h"
  24. #include "base/file.h"
  25. typedef SYS_FILE sys_fsmutex_t;
  26. typedef struct {
  27. sys_fsmutex_t mutex;
  28. char *id;
  29. #ifdef THREAD_ANY
  30. CRITICAL crit;
  31. #endif
  32. int flags;
  33. } fsmutex_s;
  34. /* ----------------------------- fsmutex_init ----------------------------- */
  35. static int
  36. _fsmutex_create(fsmutex_s *fsm, char *name, int number)
  37. {
  38. char tn[256];
  39. SYS_FILE lfd;
  40. int visible = (fsm->flags & FSMUTEX_VISIBLE ? 1 : 0);
  41. util_snprintf(tn, 256, "/tmp/%s.%d", name, number);
  42. if(!visible)
  43. unlink(tn);
  44. if( (lfd = PR_Open(tn, PR_RDWR|PR_CREATE_FILE, 0644)) == NULL)
  45. return -1;
  46. if(!visible)
  47. unlink(tn);
  48. else
  49. fsm->id = PERM_STRDUP(tn);
  50. fsm->mutex = lfd;
  51. return 0;
  52. }
  53. NSAPI_PUBLIC FSMUTEX
  54. fsmutex_init(char *name, int number, int flags)
  55. {
  56. fsmutex_s *ret = (fsmutex_s *) PERM_MALLOC(sizeof(fsmutex_s));
  57. ret->flags = flags;
  58. if(_fsmutex_create(ret, name, number) == -1) {
  59. PERM_FREE(ret);
  60. return NULL;
  61. }
  62. #ifdef THREAD_ANY
  63. if(flags & FSMUTEX_NEEDCRIT)
  64. ret->crit = crit_init();
  65. #endif
  66. return (FSMUTEX) ret;
  67. }
  68. NSAPI_PUBLIC void
  69. fsmutex_setowner(FSMUTEX fsm, uid_t uid, gid_t gid)
  70. {
  71. if(!geteuid()) {
  72. int rc = chown( ((fsmutex_s *)fsm)->id, uid, gid);
  73. PR_ASSERT(rc == 0);
  74. if (rc != 0 ) {
  75. return; /* just to suppress compiler warning... */
  76. }
  77. }
  78. }
  79. /* -------------------------- fsmutex_terminate --------------------------- */
  80. static void
  81. _fsmutex_delete(fsmutex_s *fsm)
  82. {
  83. if(fsm->flags & FSMUTEX_VISIBLE)
  84. unlink(fsm->id);
  85. PERM_FREE(fsm->id);
  86. PR_Close(fsm->mutex);
  87. }
  88. NSAPI_PUBLIC void
  89. fsmutex_terminate(FSMUTEX id)
  90. {
  91. fsmutex_s *fsm = (fsmutex_s *) id;
  92. _fsmutex_delete(fsm);
  93. #ifdef THREAD_ANY
  94. if(fsm->flags & FSMUTEX_NEEDCRIT)
  95. crit_terminate(fsm->crit);
  96. #endif
  97. PERM_FREE(fsm);
  98. }
  99. /* ----------------------------- fsmutex_lock ----------------------------- */
  100. NSAPI_PUBLIC void
  101. fsmutex_lock(FSMUTEX id)
  102. {
  103. fsmutex_s *fsm = (fsmutex_s *) id;
  104. #ifdef THREAD_ANY
  105. if(fsm->flags & FSMUTEX_NEEDCRIT)
  106. crit_enter(fsm->crit);
  107. #endif
  108. #ifdef THREAD_NSPR_USER
  109. /* Poll to avoid blocking. XXXrobm If errno is wrong this may go awry. */
  110. while(system_tlock(fsm->mutex) == -1)
  111. systhread_sleep(1000);
  112. #else
  113. system_flock(fsm->mutex );
  114. #endif
  115. }
  116. /* ---------------------------- fsmutex_unlock ---------------------------- */
  117. NSAPI_PUBLIC void
  118. fsmutex_unlock(FSMUTEX id)
  119. {
  120. fsmutex_s *fsm = (fsmutex_s *) id;
  121. system_ulock(fsm->mutex);
  122. #ifdef THREAD_ANY
  123. if(fsm->flags & FSMUTEX_NEEDCRIT)
  124. crit_exit(fsm->crit);
  125. #endif
  126. }