fsmutex.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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. (void) chown( ((fsmutex_s *)fsm)->id, uid, gid);
  73. }
  74. /* -------------------------- fsmutex_terminate --------------------------- */
  75. static void
  76. _fsmutex_delete(fsmutex_s *fsm)
  77. {
  78. if(fsm->flags & FSMUTEX_VISIBLE)
  79. unlink(fsm->id);
  80. PERM_FREE(fsm->id);
  81. PR_Close(fsm->mutex);
  82. }
  83. NSAPI_PUBLIC void
  84. fsmutex_terminate(FSMUTEX id)
  85. {
  86. fsmutex_s *fsm = (fsmutex_s *) id;
  87. _fsmutex_delete(fsm);
  88. #ifdef THREAD_ANY
  89. if(fsm->flags & FSMUTEX_NEEDCRIT)
  90. crit_terminate(fsm->crit);
  91. #endif
  92. PERM_FREE(fsm);
  93. }
  94. /* ----------------------------- fsmutex_lock ----------------------------- */
  95. NSAPI_PUBLIC void
  96. fsmutex_lock(FSMUTEX id)
  97. {
  98. fsmutex_s *fsm = (fsmutex_s *) id;
  99. #ifdef THREAD_ANY
  100. if(fsm->flags & FSMUTEX_NEEDCRIT)
  101. crit_enter(fsm->crit);
  102. #endif
  103. #ifdef THREAD_NSPR_USER
  104. /* Poll to avoid blocking. XXXrobm If errno is wrong this may go awry. */
  105. while(system_tlock(fsm->mutex) == -1)
  106. systhread_sleep(1000);
  107. #else
  108. system_flock(fsm->mutex );
  109. #endif
  110. }
  111. /* ---------------------------- fsmutex_unlock ---------------------------- */
  112. NSAPI_PUBLIC void
  113. fsmutex_unlock(FSMUTEX id)
  114. {
  115. fsmutex_s *fsm = (fsmutex_s *) id;
  116. system_ulock(fsm->mutex);
  117. #ifdef THREAD_ANY
  118. if(fsm->flags & FSMUTEX_NEEDCRIT)
  119. crit_exit(fsm->crit);
  120. #endif
  121. }