semaphore.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  4. //
  5. // Licensed to the .NET Foundation under one or more agreements.
  6. // The .NET Foundation licenses this file to you under the MIT license.
  7. // See the LICENSE file in the project root for more information.
  8. /*++
  9. Module Name:
  10. semaphore.cpp
  11. Abstract:
  12. Implementation of the sempahore synchroniztion object as described in
  13. the WIN32 API
  14. Revision History:
  15. --*/
  16. #include "pal/semaphore.hpp"
  17. #include "pal/thread.hpp"
  18. #include "pal/dbgmsg.h"
  19. using namespace CorUnix;
  20. /* ------------------- Definitions ------------------------------*/
  21. SET_DEFAULT_DEBUG_CHANNEL(SYNC);
  22. CObjectType CorUnix::otSemaphore(
  23. otiSemaphore,
  24. NULL, // No cleanup routine
  25. NULL, // No initialization routine
  26. sizeof(SemaphoreImmutableData),
  27. // NULL, // No immutable data copy routine
  28. // NULL, // No immutable data cleanup routine
  29. 0, // No process local data
  30. // NULL, // No process local data cleanup routine
  31. 0, // No shared data
  32. 0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security)
  33. CObjectType::SecuritySupported,
  34. CObjectType::SecurityInfoNotPersisted,
  35. CObjectType::UnnamedObject,
  36. CObjectType::LocalDuplicationOnly,
  37. CObjectType::WaitableObject,
  38. CObjectType::ObjectCanBeUnsignaled,
  39. CObjectType::ThreadReleaseAltersSignalCount,
  40. CObjectType::NoOwner
  41. );
  42. CAllowedObjectTypes aotSempahore(otiSemaphore);
  43. /*++
  44. Function:
  45. CreateSemaphoreExA
  46. Note:
  47. lpSemaphoreAttributes currently ignored:
  48. -- Win32 object security not supported
  49. -- handles to semaphore objects are not inheritable
  50. Parameters:
  51. See MSDN doc.
  52. --*/
  53. HANDLE
  54. PALAPI
  55. CreateSemaphoreExA(
  56. IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  57. IN LONG lInitialCount,
  58. IN LONG lMaximumCount,
  59. IN LPCSTR lpName,
  60. IN /*_Reserved_*/ DWORD dwFlags,
  61. IN DWORD dwDesiredAccess)
  62. {
  63. // dwFlags is reserved and unused, and dwDesiredAccess is currently
  64. // only ever used as SEMAPHORE_ALL_ACCESS. The other parameters
  65. // all map to CreateSemaphoreA.
  66. _ASSERTE(SEMAPHORE_ALL_ACCESS == dwDesiredAccess);
  67. return CreateSemaphoreA(
  68. lpSemaphoreAttributes,
  69. lInitialCount,
  70. lMaximumCount,
  71. lpName);
  72. }
  73. /*++
  74. Function:
  75. CreateSemaphoreA
  76. Note:
  77. lpSemaphoreAttributes currently ignored:
  78. -- Win32 object security not supported
  79. -- handles to semaphore objects are not inheritable
  80. Parameters:
  81. See MSDN doc.
  82. --*/
  83. HANDLE
  84. PALAPI
  85. CreateSemaphoreA(
  86. IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  87. IN LONG lInitialCount,
  88. IN LONG lMaximumCount,
  89. IN LPCSTR lpName)
  90. {
  91. HANDLE hSemaphore = NULL;
  92. CPalThread *pthr = NULL;
  93. PAL_ERROR palError;
  94. PERF_ENTRY(CreateSemaphoreA);
  95. ENTRY("CreateSemaphoreA(lpSemaphoreAttributes=%p, lInitialCount=%d, "
  96. "lMaximumCount=%d, lpName=%p (%s))\n",
  97. lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, lpName?lpName:"NULL");
  98. pthr = InternalGetCurrentThread();
  99. if (lpName != nullptr)
  100. {
  101. ASSERT("lpName: Cross-process named objects are not supported in PAL");
  102. palError = ERROR_NOT_SUPPORTED;
  103. }
  104. else
  105. {
  106. palError = InternalCreateSemaphore(
  107. pthr,
  108. lpSemaphoreAttributes,
  109. lInitialCount,
  110. lMaximumCount,
  111. NULL,
  112. &hSemaphore
  113. );
  114. }
  115. //
  116. // We always need to set last error, even on success:
  117. // we need to protect ourselves from the situation
  118. // where last error is set to ERROR_ALREADY_EXISTS on
  119. // entry to the function
  120. //
  121. pthr->SetLastError(palError);
  122. LOGEXIT("CreateSemaphoreA returns HANDLE %p\n", hSemaphore);
  123. PERF_EXIT(CreateSemaphoreA);
  124. return hSemaphore;
  125. }
  126. /*++
  127. Function:
  128. CreateSemaphoreExW
  129. Note:
  130. lpSemaphoreAttributes currentely ignored:
  131. -- Win32 object security not supported
  132. -- handles to semaphore objects are not inheritable
  133. Parameters:
  134. See MSDN doc.
  135. --*/
  136. HANDLE
  137. PALAPI
  138. CreateSemaphoreExW(
  139. IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  140. IN LONG lInitialCount,
  141. IN LONG lMaximumCount,
  142. IN LPCWSTR lpName,
  143. IN /*_Reserved_*/ DWORD dwFlags,
  144. IN DWORD dwDesiredAccess)
  145. {
  146. // dwFlags is reserved and unused
  147. return CreateSemaphoreW(
  148. lpSemaphoreAttributes,
  149. lInitialCount,
  150. lMaximumCount,
  151. lpName);
  152. }
  153. /*++
  154. Function:
  155. CreateSemaphoreW
  156. Note:
  157. lpSemaphoreAttributes currentely ignored:
  158. -- Win32 object security not supported
  159. -- handles to semaphore objects are not inheritable
  160. Parameters:
  161. See MSDN doc.
  162. --*/
  163. HANDLE
  164. PALAPI
  165. CreateSemaphoreW(
  166. IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  167. IN LONG lInitialCount,
  168. IN LONG lMaximumCount,
  169. IN LPCWSTR lpName)
  170. {
  171. HANDLE hSemaphore = NULL;
  172. PAL_ERROR palError;
  173. CPalThread *pthr = NULL;
  174. PERF_ENTRY(CreateSemaphoreW);
  175. ENTRY("CreateSemaphoreW(lpSemaphoreAttributes=%p, lInitialCount=%d, "
  176. "lMaximumCount=%d, lpName=%p (%S))\n",
  177. lpSemaphoreAttributes, lInitialCount, lMaximumCount,
  178. lpName, lpName?lpName:W16_NULLSTRING);
  179. pthr = InternalGetCurrentThread();
  180. palError = InternalCreateSemaphore(
  181. pthr,
  182. lpSemaphoreAttributes,
  183. lInitialCount,
  184. lMaximumCount,
  185. lpName,
  186. &hSemaphore
  187. );
  188. //
  189. // We always need to set last error, even on success:
  190. // we need to protect ourselves from the situation
  191. // where last error is set to ERROR_ALREADY_EXISTS on
  192. // entry to the function
  193. //
  194. pthr->SetLastError(palError);
  195. LOGEXIT("CreateSemaphoreW returns HANDLE %p\n", hSemaphore);
  196. PERF_EXIT(CreateSemaphoreW);
  197. return hSemaphore;
  198. }
  199. /*++
  200. Function:
  201. InternalCreateSemaphore
  202. Note:
  203. lpSemaphoreAttributes currentely ignored:
  204. -- Win32 object security not supported
  205. -- handles to semaphore objects are not inheritable
  206. Parameters
  207. pthr -- thread data for calling thread
  208. phEvent -- on success, receives the allocated semaphore handle
  209. See MSDN docs on CreateSemaphore for all other parameters.
  210. --*/
  211. PAL_ERROR
  212. CorUnix::InternalCreateSemaphore(
  213. CPalThread *pthr,
  214. LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  215. LONG lInitialCount,
  216. LONG lMaximumCount,
  217. LPCWSTR lpName,
  218. HANDLE *phSemaphore
  219. )
  220. {
  221. CObjectAttributes oa(lpName, lpSemaphoreAttributes);
  222. PAL_ERROR palError = NO_ERROR;
  223. IPalObject *pobjSemaphore = NULL;
  224. IPalObject *pobjRegisteredSemaphore = NULL;
  225. SemaphoreImmutableData *pSemaphoreData;
  226. _ASSERTE(NULL != pthr);
  227. _ASSERTE(NULL != phSemaphore);
  228. ENTRY("InternalCreateSemaphore(pthr=%p, lpSemaphoreAttributes=%p, "
  229. "lInitialCount=%d, lMaximumCount=%d, lpName=%p, phSemaphore=%p)\n",
  230. pthr,
  231. lpSemaphoreAttributes,
  232. lInitialCount,
  233. lMaximumCount,
  234. lpName,
  235. phSemaphore
  236. );
  237. if (lpName != nullptr)
  238. {
  239. ASSERT("lpName: Cross-process named objects are not supported in PAL");
  240. palError = ERROR_NOT_SUPPORTED;
  241. goto InternalCreateSemaphoreExit;
  242. }
  243. if (lMaximumCount <= 0)
  244. {
  245. ERROR("lMaximumCount is invalid (%d)\n", lMaximumCount);
  246. palError = ERROR_INVALID_PARAMETER;
  247. goto InternalCreateSemaphoreExit;
  248. }
  249. if ((lInitialCount < 0) || (lInitialCount > lMaximumCount))
  250. {
  251. ERROR("lInitialCount is invalid (%d)\n", lInitialCount);
  252. palError = ERROR_INVALID_PARAMETER;
  253. goto InternalCreateSemaphoreExit;
  254. }
  255. palError = g_pObjectManager->AllocateObject(
  256. pthr,
  257. &otSemaphore,
  258. &oa,
  259. &pobjSemaphore
  260. );
  261. if (NO_ERROR != palError)
  262. {
  263. goto InternalCreateSemaphoreExit;
  264. }
  265. palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData));
  266. if (NO_ERROR != palError)
  267. {
  268. ASSERT("Error %d obtaining object data\n", palError);
  269. goto InternalCreateSemaphoreExit;
  270. }
  271. pSemaphoreData->lMaximumCount = lMaximumCount;
  272. if (0 != lInitialCount)
  273. {
  274. ISynchStateController *pssc;
  275. palError = pobjSemaphore->GetSynchStateController(
  276. pthr,
  277. &pssc
  278. );
  279. if (NO_ERROR == palError)
  280. {
  281. palError = pssc->SetSignalCount(lInitialCount);
  282. pssc->ReleaseController();
  283. }
  284. if (NO_ERROR != palError)
  285. {
  286. ASSERT("Unable to set new semaphore state (%d)\n", palError);
  287. goto InternalCreateSemaphoreExit;
  288. }
  289. }
  290. palError = g_pObjectManager->RegisterObject(
  291. pthr,
  292. pobjSemaphore,
  293. &aotSempahore,
  294. 0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security)
  295. phSemaphore,
  296. &pobjRegisteredSemaphore
  297. );
  298. //
  299. // pobjSemaphore is invalidated by the call to RegisterObject, so NULL it
  300. // out here to ensure that we don't try to release a reference on
  301. // it down the line.
  302. //
  303. pobjSemaphore = NULL;
  304. InternalCreateSemaphoreExit:
  305. if (NULL != pobjSemaphore)
  306. {
  307. pobjSemaphore->ReleaseReference(pthr);
  308. }
  309. if (NULL != pobjRegisteredSemaphore)
  310. {
  311. pobjRegisteredSemaphore->ReleaseReference(pthr);
  312. }
  313. LOGEXIT("InternalCreateSemaphore returns %d\n", palError);
  314. return palError;
  315. }
  316. /*++
  317. Function:
  318. ReleaseSemaphore
  319. Parameters:
  320. See MSDN doc.
  321. --*/
  322. BOOL
  323. PALAPI
  324. ReleaseSemaphore(
  325. IN HANDLE hSemaphore,
  326. IN LONG lReleaseCount,
  327. OUT LPLONG lpPreviousCount)
  328. {
  329. PAL_ERROR palError = NO_ERROR;
  330. CPalThread *pthr = NULL;
  331. PERF_ENTRY(ReleaseSemaphore);
  332. ENTRY("ReleaseSemaphore(hSemaphore=%p, lReleaseCount=%d, "
  333. "lpPreviousCount=%p)\n",
  334. hSemaphore, lReleaseCount, lpPreviousCount);
  335. pthr = InternalGetCurrentThread();
  336. palError = InternalReleaseSemaphore(
  337. pthr,
  338. hSemaphore,
  339. lReleaseCount,
  340. lpPreviousCount
  341. );
  342. if (NO_ERROR != palError)
  343. {
  344. pthr->SetLastError(palError);
  345. }
  346. LOGEXIT ("ReleaseSemaphore returns BOOL %d\n", (NO_ERROR == palError));
  347. PERF_EXIT(ReleaseSemaphore);
  348. return (NO_ERROR == palError);
  349. }
  350. /*++
  351. Function:
  352. InternalReleaseSemaphore
  353. Parameters:
  354. pthr -- thread data for calling thread
  355. See MSDN docs on ReleaseSemaphore for all other parameters
  356. --*/
  357. PAL_ERROR
  358. CorUnix::InternalReleaseSemaphore(
  359. CPalThread *pthr,
  360. HANDLE hSemaphore,
  361. LONG lReleaseCount,
  362. LPLONG lpPreviousCount
  363. )
  364. {
  365. PAL_ERROR palError = NO_ERROR;
  366. IPalObject *pobjSemaphore = NULL;
  367. ISynchStateController *pssc = NULL;
  368. SemaphoreImmutableData *pSemaphoreData;
  369. LONG lOldCount;
  370. _ASSERTE(NULL != pthr);
  371. ENTRY("InternalReleaseSempahore(pthr=%p, hSemaphore=%p, lReleaseCount=%d, "
  372. "lpPreviousCount=%p)\n",
  373. pthr,
  374. hSemaphore,
  375. lReleaseCount,
  376. lpPreviousCount
  377. );
  378. if (0 >= lReleaseCount)
  379. {
  380. palError = ERROR_INVALID_PARAMETER;
  381. goto InternalReleaseSemaphoreExit;
  382. }
  383. palError = g_pObjectManager->ReferenceObjectByHandle(
  384. pthr,
  385. hSemaphore,
  386. &aotSempahore,
  387. 0, // Should be SEMAPHORE_MODIFY_STATE; currently ignored (no Win32 security)
  388. &pobjSemaphore
  389. );
  390. if (NO_ERROR != palError)
  391. {
  392. ERROR("Unable to obtain object for handle %p (error %d)!\n", hSemaphore, palError);
  393. goto InternalReleaseSemaphoreExit;
  394. }
  395. palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData));
  396. if (NO_ERROR != palError)
  397. {
  398. ASSERT("Error %d obtaining object data\n", palError);
  399. goto InternalReleaseSemaphoreExit;
  400. }
  401. palError = pobjSemaphore->GetSynchStateController(
  402. pthr,
  403. &pssc
  404. );
  405. if (NO_ERROR != palError)
  406. {
  407. ASSERT("Error %d obtaining synch state controller\n", palError);
  408. goto InternalReleaseSemaphoreExit;
  409. }
  410. palError = pssc->GetSignalCount(&lOldCount);
  411. if (NO_ERROR != palError)
  412. {
  413. ASSERT("Error %d obtaining current signal count\n", palError);
  414. goto InternalReleaseSemaphoreExit;
  415. }
  416. _ASSERTE(lOldCount <= pSemaphoreData->lMaximumCount);
  417. if (lReleaseCount > pSemaphoreData->lMaximumCount - lOldCount)
  418. {
  419. palError = ERROR_INVALID_PARAMETER;
  420. goto InternalReleaseSemaphoreExit;
  421. }
  422. palError = pssc->IncrementSignalCount(lReleaseCount);
  423. if (NO_ERROR != palError)
  424. {
  425. ASSERT("Error %d incrementing signal count\n", palError);
  426. goto InternalReleaseSemaphoreExit;
  427. }
  428. if (NULL != lpPreviousCount)
  429. {
  430. *lpPreviousCount = lOldCount;
  431. }
  432. InternalReleaseSemaphoreExit:
  433. if (NULL != pssc)
  434. {
  435. pssc->ReleaseController();
  436. }
  437. if (NULL != pobjSemaphore)
  438. {
  439. pobjSemaphore->ReleaseReference(pthr);
  440. }
  441. LOGEXIT("InternalReleaseSemaphore returns %d\n", palError);
  442. return palError;
  443. }
  444. // TODO: Implementation of OpenSemaphoreA() doesn't exist, do we need it? More generally, do we need the A versions at all?
  445. /*++
  446. Function:
  447. OpenSemaphoreW
  448. Note:
  449. dwDesiredAccess is currently ignored (no Win32 object security support)
  450. bInheritHandle is currently ignored (handles to semaphore are not inheritable)
  451. Parameters:
  452. See MSDN doc.
  453. --*/
  454. HANDLE
  455. PALAPI
  456. OpenSemaphoreW(
  457. IN DWORD dwDesiredAccess,
  458. IN BOOL bInheritHandle,
  459. IN LPCWSTR lpName)
  460. {
  461. HANDLE hSemaphore = NULL;
  462. PAL_ERROR palError = NO_ERROR;
  463. CPalThread *pthr = NULL;
  464. PERF_ENTRY(OpenSemaphoreW);
  465. ENTRY("OpenSemaphoreW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n",
  466. dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);
  467. pthr = InternalGetCurrentThread();
  468. /* validate parameters */
  469. if (lpName == nullptr)
  470. {
  471. ERROR("lpName is NULL\n");
  472. palError = ERROR_INVALID_PARAMETER;
  473. }
  474. else
  475. {
  476. ASSERT("lpName: Cross-process named objects are not supported in PAL");
  477. palError = ERROR_NOT_SUPPORTED;
  478. }
  479. if (NO_ERROR != palError)
  480. {
  481. pthr->SetLastError(palError);
  482. }
  483. LOGEXIT("OpenSemaphoreW returns HANDLE %p\n", hSemaphore);
  484. PERF_EXIT(OpenSemaphoreW);
  485. return hSemaphore;
  486. }