Initial import of Scalos. To decrease size I have
[AROS-Contrib.git] / scalos / main / Semaphores.c
blob6529f23fae6aa3c58a94756cea0f49566cea396c
1 // Semaphores.c
2 // $Date$
3 // $Revision$
6 #include <exec/types.h>
7 #include <utility/hooks.h>
8 #include <dos/dos.h>
9 #include <dos/dostags.h>
11 #define __USE_SYSBASE
13 #include <proto/dos.h>
14 #include <proto/exec.h>
15 #include "debug.h"
16 #include <proto/scalos.h>
18 #include <clib/alib_protos.h>
20 #include <proto/utility.h>
22 #include <defs.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stddef.h>
29 #include <limits.h>
31 #include "scalos_structures.h"
32 #include "functions.h"
33 #include "Variables.h"
35 //----------------------------------------------------------------------------
37 // local functions
39 //----------------------------------------------------------------------------
41 // public Data
43 struct ScalosSemaphoreList GlobalSemaphoreList[] =
45 { &WBStartListSema, "WBStartListSema" },
46 { &LayersSema, "LayersSema" },
47 { &MenuSema, "MenuSema" },
48 { &CopyHookSemaphore, "CopyHookSemaphore" },
49 { &DefIconsSemaphore, "DefIconsSemaphore" },
50 { &DefIconsCacheSemaphore, "DefIconsCacheSemaphore" },
51 { &DeleteHookSemaphore, "DeleteHookSemaphore" },
52 { &FileTypeListSema, "FileTypeListSema" },
53 { &TextInputHookSemaphore, "TextInputHookSemaphore" },
54 { &QuitSemaphore, "QuitSemaphore" },
55 { &CloseWBHookListSemaphore, "CloseWBHookListSemaphore" },
56 { &ClassListSemaphore, "ClassListSemaphore" },
57 { &WinListSemaphore, "WinListSemaphore" },
58 { &DoWaitSemaphore, "DoWaitSemaphore" },
59 { &PatternSema, "PatternSema" },
60 { &ParseMenuListSemaphore, "ParseMenuListSemaphore" },
61 { &ListenerSema, "ListenerSema" },
62 { &MenuSemaphore, "MenuSemaphore" },
63 { &AppMenuListSemaphore, "AppMenuListSemaphore" },
64 { &ThumbnailsCleanupSemaphore, "ThumbnailsCleanupSemaphore" },
65 { &tteSema, "tteSema" },
66 { &ClipboardSemaphore, "ClipboardSemaphore" },
67 { &UndoListListSemaphore, "UndoListListSemaphore" },
68 { &RedoListListSemaphore, "RedoListListSemaphore" },
69 { NULL, NULL }
72 //----------------------------------------------------------------------------
74 // local Data
76 //----------------------------------------------------------------------------
78 // +jl+ 20010915
79 // extension to ScalosAttemptSemaphore()
80 // - prevents nesting when called more than once from same task
81 BOOL AttemptSemaphoreNoNest(SCALOSSEMAPHORE *sema)
83 if (!ScalosAttemptSemaphore(sema))
84 return FALSE;
86 if (sema->Sema.ss_NestCount > 1)
88 ScalosReleaseSemaphore(sema);
89 return FALSE;
92 return TRUE;
96 // Try to obtain multiple Semaphores without deadlock
97 // advantages over system ObtainSemaphoreList() :
98 // - supports both exclusive and shared Semaphore access.
99 // - does not use Semaphore Node data.
100 #if !defined(ScaObtainSemaphoreList)
101 void ScaObtainSemaphoreList(ULONG FirstTag, ...)
103 va_list args;
104 struct TagItem *TagList;
106 va_start(args, FirstTag);
108 TagList = ScalosVTagList(FirstTag, args);
109 if (TagList)
111 ScaObtainSemaphoreListA(TagList);
112 FreeTagItems(TagList);
115 va_end(args);
117 #endif /* ScaObtainSemaphoreList */
119 void ScaObtainSemaphoreListA(struct TagItem *OrigTagList)
121 struct TagItem *Tag;
122 BOOL GlobalSuccess;
124 d1(KPrintF("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
126 do {
127 struct TagItem *TagList = OrigTagList;
129 GlobalSuccess = TRUE;
131 d1(kprintf("%s/%s/%ld: Loop START\n", __FILE__, __FUNC__, __LINE__));
133 Forbid();
134 while (GlobalSuccess && (Tag = NextTagItem(&TagList)))
136 BOOL Success = TRUE;
138 d1(KPrintF("%s/%s/%ld: Tag=%08lx ti_Tag=%08lx Sema=%08lx\n", __FILE__, __FUNC__, __LINE__, Tag, Tag->ti_Tag, Tag->ti_Data));
140 switch (Tag->ti_Tag)
142 case SCA_SemaphoreExclusive:
143 Success = ScalosAttemptSemaphore((SCALOSSEMAPHORE *) Tag->ti_Data);
144 break;
146 case SCA_SemaphoreShared:
147 Success = ScalosAttemptSemaphoreShared((SCALOSSEMAPHORE *) Tag->ti_Data);
148 break;
151 d1(KPrintF("%s/%s/%ld: Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
153 if (!Success)
155 struct TagItem *Tag2, *TagList2 = OrigTagList;
157 GlobalSuccess = FALSE;
159 // Release all previously obtained semaphores
160 while ((Tag2 = NextTagItem(&TagList2)) && Tag2 != Tag)
162 d1(KPrintF("%s/%s/%ld: Tag2=%08lx ti_Tag=%08lx Sema=%08lx\n", __FILE__, __FUNC__, __LINE__, Tag2, Tag2->ti_Tag, Tag2->ti_Data));
163 ScalosReleaseSemaphore((SCALOSSEMAPHORE *) Tag2->ti_Data);
166 // wait until Semaphore available
167 d1(kprintf("%s/%s/%ld: before Wait\n", __FILE__, __FUNC__, __LINE__));
168 switch (Tag->ti_Tag)
170 case SCA_SemaphoreExclusive:
171 ScalosObtainSemaphore((SCALOSSEMAPHORE *) Tag->ti_Data); // breaks Forbid()
172 break;
173 case SCA_SemaphoreShared:
174 ScalosObtainSemaphoreShared((SCALOSSEMAPHORE *) Tag->ti_Data); // breaks Forbid()
175 break;
178 d1(KPrintF("%s/%s/%ld: after Wait\n", __FILE__, __FUNC__, __LINE__));
180 Permit();
181 Forbid();
182 ScalosReleaseSemaphore((SCALOSSEMAPHORE *) Tag->ti_Data);
185 Permit();
186 d1(KPrintF("%s/%s/%ld: GlobalSuccess=%ld\n", __FILE__, __FUNC__, __LINE__, GlobalSuccess));
187 } while (!GlobalSuccess);
189 d1(KPrintF("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
193 // Try to obtain multiple Semaphores without deadlock
194 // advantages over system ObtainSemaphoreList() :
195 // - supports both exclusive and shared Semaphore access.
196 // - does not use Semaphore Node data.
197 #if !defined(ScaAttemptSemaphoreList)
198 BOOL ScaAttemptSemaphoreList(ULONG FirstTag, ...)
200 va_list args;
201 struct TagItem *TagList;
202 BOOL Success = FALSE;
204 va_start(args, FirstTag);
206 TagList = ScalosVTagList(FirstTag, args);
207 if (TagList)
209 Success = ScaAttemptSemaphoreListA(TagList);
210 FreeTagItems(TagList);
213 va_end(args);
215 return Success;
217 #endif /* ScaAttemptSemaphoreListA */
220 BOOL ScaAttemptSemaphoreListA(struct TagItem *OriginalTagList)
222 struct TagItem *TagList;
223 struct TagItem *Tag;
224 BOOL Success = TRUE;
226 d1(kprintf("%s/%s/%ld: START\n", __FILE__, __FUNC__, __LINE__));
228 TagList = OriginalTagList;
230 Forbid();
231 while (Success && (Tag = NextTagItem(&TagList)))
233 d1(kprintf("%s/%s/%ld: Tag=%08lx ti_Tag=%08lx Sema=%08lx\n", __FILE__, __FUNC__, __LINE__, Tag, Tag->ti_Tag, Tag->ti_Data));
235 switch (Tag->ti_Tag)
237 case SCA_SemaphoreExclusive:
238 Success = ScalosAttemptSemaphore((SCALOSSEMAPHORE *) Tag->ti_Data);
239 break;
241 case SCA_SemaphoreShared:
242 Success = ScalosAttemptSemaphoreShared((SCALOSSEMAPHORE *) Tag->ti_Data);
243 break;
245 case SCA_SemaphoreExclusiveNoNest:
246 Success = AttemptSemaphoreNoNest((SCALOSSEMAPHORE *) Tag->ti_Data);
247 break;
250 d1(kprintf("%s/%s/%ld: Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
252 if (!Success)
254 struct TagItem *Tag2, *TagList2 = OriginalTagList;
256 // Release all previously obtained semaphores
257 while ((Tag2 = NextTagItem(&TagList2)) && Tag2 != Tag)
259 d1(kprintf("%s/%s/%ld: Tag2=%08lx ti_Tag=%08lx Sema=%08lx\n", __FILE__, __FUNC__, __LINE__, Tag2, Tag2->ti_Tag, Tag2->ti_Data));
260 ScalosReleaseSemaphore((SCALOSSEMAPHORE *) Tag2->ti_Data);
264 Permit();
266 d1(kprintf("%s/%s/%ld: END Success=%ld\n", __FILE__, __FUNC__, __LINE__, Success));
268 return Success;
272 #ifdef DEBUG_SEMAPHORES
274 #undef SignalSemaphore
276 void DebugScalosLockIconListShared(struct internalScaWindowTask *iwt,
277 CONST_STRPTR CallingFile, CONST_STRPTR CallingFunc, ULONG CallingLine)
279 d1(KPrintF("%s/%s/%ld: START iwt=%08lx <%s>\n", __FILE__, __FUNC__, __LINE__, iwt, iwt->iwt_WinTitle ? iwt->iwt_WinTitle : (STRPTR) ""));
281 // Problem addressed: if the current process already holds an exclusive
282 // lock on the semaphore, ObtainSemaphoreShared() is guaranteed to
283 // create a deadlock.
284 // Solution: is we already own this semaphore exclusively,
285 // ScalosAttemptSemaphore() will succeed.
286 if (DebugScalosAttemptSemaphoreShared(iwt->iwt_WindowTask.wt_IconSemaphore, CallingFile, CallingFunc, CallingLine))
288 if (iwt->iwt_WindowProcess == (struct Process *) FindTask(NULL))
290 iwt->iwt_IconListLockedShared++;
292 d1(kprintf("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
293 return;
295 if (DebugScalosAttemptSemaphore(iwt->iwt_WindowTask.wt_IconSemaphore, CallingFile, CallingFunc, CallingLine))
297 if (iwt->iwt_WindowProcess == (struct Process *) FindTask(NULL))
299 iwt->iwt_IconListLockedExclusive++;
301 d1(kprintf("%s/%s/%ld: END\n", __FILE__, __FUNC__, __LINE__));
302 return;
305 d1(kprintf("%s/%s/%ld: \n", __FILE__, __FUNC__, __LINE__));
307 DebugScalosObtainSemaphoreShared(iwt->iwt_WindowTask.wt_IconSemaphore, CallingFile, CallingFunc, CallingLine);
309 if (iwt->iwt_WindowProcess == (struct Process *) FindTask(NULL))
311 iwt->iwt_IconListLockedShared++;
314 d1(KPrintF("%s/%s/%ld: END iwt=%08lx <%s>\n", __FILE__, __FUNC__, __LINE__, iwt, iwt->iwt_WinTitle ? iwt->iwt_WinTitle : (STRPTR) ""));
318 void DebugScalosLockIconListExclusive(struct internalScaWindowTask *iwt,
319 CONST_STRPTR CallingFile, CONST_STRPTR CallingFunc, ULONG CallingLine)
321 d1(KPrintF("%s/%s/%ld: START iwt=%08lx <%s>\n", __FILE__, __FUNC__, __LINE__, iwt, iwt->iwt_WinTitle ? iwt->iwt_WinTitle : (STRPTR) ""));
323 if (iwt->iwt_WindowProcess == (struct Process *) FindTask(NULL)
324 && iwt->iwt_IconListLockedShared)
326 // the window process already holds a shared lock on the icon list.
327 // calling ScalosObtainSemaphore now guarantees a deadlock.
328 ULONG Count = 0;
330 d1(kprintf("%s/%s/%ld: iwt_IconListLockedShared=%lu iwt_IconListLockedExclusive=%lu\n", \
331 __FILE__, __FUNC__, __LINE__, iwt->iwt_IconListLockedShared, iwt->iwt_IconListLockedExclusive));
333 Forbid();
335 // release all shared locks, and establish exclusive lock(s)
336 while (iwt->iwt_IconListLockedShared)
338 iwt->iwt_IconListLockedShared--;
339 Count++;
340 ScalosReleaseSemaphore(iwt->iwt_WindowTask.wt_IconSemaphore);
342 while (Count--)
344 iwt->iwt_IconListLockedExclusive++;
345 ScalosObtainSemaphore(iwt->iwt_WindowTask.wt_IconSemaphore);
348 Permit();
350 d1(kprintf("%s/%s/%ld: iwt_IconListLockedShared=%lu iwt_IconListLockedExclusive=%lu\n", \
351 __FILE__, __FUNC__, __LINE__, iwt->iwt_IconListLockedShared, iwt->iwt_IconListLockedExclusive));
354 DebugScalosObtainSemaphore(iwt->iwt_WindowTask.wt_IconSemaphore, CallingFile, CallingFunc, CallingLine);
356 if (iwt->iwt_WindowProcess == (struct Process *) FindTask(NULL))
358 iwt->iwt_IconListLockedExclusive++;
361 d1(KPrintF("%s/%s/%ld: END iwt=%08lx <%s>\n", __FILE__, __FUNC__, __LINE__, iwt, iwt->iwt_WinTitle ? iwt->iwt_WinTitle : (STRPTR) ""));
366 struct ScaWindowList *DebugSCA_LockWindowList(LONG accessmode,
367 CONST_STRPTR CallingFile, CONST_STRPTR CallingFunc, ULONG CallingLine)
369 switch (accessmode)
371 case SCA_LockWindowList_Shared:
372 DebugScalosObtainSemaphoreShared(&WinListSemaphore,
373 CallingFile, CallingFunc, CallingLine);
374 break;
375 case SCA_LockWindowList_Exclusiv:
376 DebugScalosObtainSemaphore(&WinListSemaphore,
377 CallingFile, CallingFunc, CallingLine);
378 break;
379 default:
380 break;
383 return &winlist;
387 struct ScalosSemaphore *DebugScalosCreateSemaphore(CONST_STRPTR CallingFile,
388 CONST_STRPTR CallingFunc, ULONG CallingLine)
390 struct ScalosSemaphore *xsema;
392 xsema = AllocVec(sizeof(struct ScalosSemaphore), MEMF_PUBLIC | MEMF_CLEAR);
393 if (xsema)
394 DebugScalosInitSemaphore(xsema, CallingFile, CallingFunc, CallingLine);
396 return xsema;
400 void DebugScalosDeleteSemaphore(struct ScalosSemaphore *xsema,
401 CONST_STRPTR CallingFile, CONST_STRPTR CallingFunc, ULONG CallingLine)
403 if (xsema)
405 DebugScalosObtainSemaphore(xsema, CallingFile, CallingFunc, CallingLine);
406 Forbid();
407 DebugScalosReleaseSemaphore(xsema, CallingFile, CallingFunc, CallingLine);
408 FreeVec(xsema);
409 Permit();
414 void DebugScalosInitSemaphore(struct ScalosSemaphore *xsema,
415 CONST_STRPTR CallingFile,
416 CONST_STRPTR CallingFunc, ULONG CallingLine)
418 d1(kprintf("%s/%s/%ld: Begin InitSemaphore(%08lx <%s>) Task=%08lx <%s>\n", \
419 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name));
421 xsema->MagicNumber = DEBUG_SEMAPHORE_MAGIC;
422 xsema->SafetyPtr = &xsema->Sema;
424 NewList(&xsema->OwnerList);
425 NewList(&xsema->BidderList);
426 InitSemaphore(&xsema->Sema);
428 d1(kprintf("%s/%s/%ld: End InitSemaphore(%08lx <%s>)\n", \
429 CallingFile, CallingFunc, CallingLine, xsema));
433 void DebugScalosObtainSemaphore(struct ScalosSemaphore *xsema,
434 CONST_STRPTR CallingFile,
435 CONST_STRPTR CallingFunc, ULONG CallingLine)
437 struct DebugSemaOwner *Owner;
439 d1(kprintf("%s/%s/%ld: Begin ObtainSemaphore(%08lx <%s>) Task=%08lx <%s>\n", \
440 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name));
442 Owner = AllocVec(sizeof(struct DebugSemaOwner), MEMF_PUBLIC);
443 if (Owner)
445 Forbid();
446 Owner->OwnMode = OWNMODE_EXCLUSIVE;
447 Owner->FileName = CallingFile;
448 Owner->Func = CallingFunc;
449 Owner->Line = CallingLine;
450 Owner->Proc = (struct Process *) FindTask(NULL);
451 d1(if (Owner->Proc->pr_Task.tc_Node.ln_Name && 0 == strcmp(Owner->Proc->pr_Task.tc_Node.ln_Name, "input.device")) \
452 KPrintF("%s/%s/%ld: ObtainSemaphore called from input.device!\n", CallingFile, CallingFunc, CallingLine));
453 AddHead(&xsema->BidderList, &Owner->node);
454 Permit();
457 ObtainSemaphore(&xsema->Sema);
459 if (Owner)
461 Forbid();
462 Remove(&Owner->node);
463 AddHead(&xsema->OwnerList, &Owner->node);
464 Permit();
467 d1(kprintf("%s/%s/%ld: End ObtainSemaphore(%08lx <%s>)\n", \
468 CallingFile, CallingFunc, CallingLine, xsema));
472 void DebugScalosObtainSemaphoreShared(struct ScalosSemaphore *xsema,
473 CONST_STRPTR CallingFile,
474 CONST_STRPTR CallingFunc, ULONG CallingLine)
476 struct DebugSemaOwner *Owner;
478 d1(kprintf("%s/%s/%ld: Begin ObtainSemaphoreShared(%08lx <%s>) Task=%08lx <%s>\n", \
479 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name));
481 Owner = AllocVec(sizeof(struct DebugSemaOwner), MEMF_PUBLIC);
482 if (Owner)
484 Forbid();
485 Owner->OwnMode = OWNMODE_SHARED;
486 Owner->FileName = CallingFile;
487 Owner->Func = CallingFunc;
488 Owner->Line = CallingLine;
489 Owner->Proc = (struct Process *) FindTask(NULL);
490 d1(if (Owner->Proc->pr_Task.tc_Node.ln_Name && 0 == strcmp(Owner->Proc->pr_Task.tc_Node.ln_Name, "input.device")) \
491 KPrintF("%s/%s/%ld: ObtainSemaphoreShared called from input.device!\n", CallingFile, CallingFunc, CallingLine));
492 AddHead(&xsema->BidderList, &Owner->node);
493 Permit();
496 ObtainSemaphoreShared(&xsema->Sema);
498 if (Owner)
500 Forbid();
501 Remove(&Owner->node);
502 AddHead(&xsema->OwnerList, &Owner->node);
503 Permit();
506 d1(kprintf("%s/%s/%ld: End ObtainSemaphoreShared(%08lx <%s>)\n", \
507 CallingFile, CallingFunc, CallingLine, xsema));
511 void DebugScalosReleaseSemaphore(struct ScalosSemaphore *xsema,
512 CONST_STRPTR CallingFile,
513 CONST_STRPTR CallingFunc, ULONG CallingLine)
515 struct DebugSemaOwner *Owner;
516 struct Process *myProc = (struct Process *) FindTask(NULL);
517 BOOL Found = FALSE;
519 d1(kprintf("%s/%s/%ld: Begin ReleaseSemaphore(%08lx) Task=%08lx <%s>\n", \
520 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name));
522 Forbid();
523 for (Owner = (struct DebugSemaOwner *) xsema->OwnerList.lh_Head;
524 Owner != (struct DebugSemaOwner *) &xsema->OwnerList.lh_Tail;
525 Owner = (struct DebugSemaOwner *) Owner->node.ln_Succ)
527 if (Owner->Proc == myProc)
529 Found = TRUE;
530 Remove(&Owner->node);
531 FreeVec(Owner);
532 break;
535 Permit();
537 if (!Found)
539 kprintf("%s/%s/%ld: FAILED ReleaseSemaphore(%08lx) - Task %08lx (%s) never locked this Semaphore!\n", \
540 CallingFile, CallingFunc, CallingLine, xsema,
541 FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name);
544 ReleaseSemaphore(&xsema->Sema);
546 d1(kprintf("%s/%s/%ld: End ReleaseSemaphore(%08lx)\n", \
547 CallingFile, CallingFunc, CallingLine, xsema));
551 ULONG DebugScalosAttemptSemaphore(struct ScalosSemaphore *xsema,
552 CONST_STRPTR CallingFile,
553 CONST_STRPTR CallingFunc, ULONG CallingLine)
555 ULONG Result;
557 d1(kprintf("%s/%s/%ld: Begin AttemptSemaphore(%08lx) Task=%08lx <%s>\n", \
558 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), FindTask(NULL)->tc_Node.ln_Name));
560 Result = AttemptSemaphore(&xsema->Sema);
562 if (Result)
564 struct DebugSemaOwner *Owner;
566 Owner = AllocVec(sizeof(struct DebugSemaOwner), MEMF_PUBLIC);
567 if (Owner)
569 Forbid();
570 Owner->OwnMode = OWNMODE_EXCLUSIVE;
571 Owner->FileName = CallingFile;
572 Owner->Func = CallingFunc;
573 Owner->Line = CallingLine;
574 Owner->Proc = (struct Process *) FindTask(NULL);
575 AddHead(&xsema->OwnerList, &Owner->node);
576 Permit();
580 d1(kprintf("%s/%s/%ld: End AttemptSemaphore(%08lx) = %ld\n", \
581 CallingFile, CallingFunc, CallingLine, xsema, Result));
583 return Result;
587 ULONG DebugScalosAttemptSemaphoreShared(struct ScalosSemaphore *xsema,
588 CONST_STRPTR CallingFile,
589 CONST_STRPTR CallingFunc, ULONG CallingLine)
591 ULONG Result;
593 d1(kprintf("%s/%s/%ld: Begin AttemptSemaphoreShared(%08lx) Task=%08lx <%s>\n", \
594 CallingFile, CallingFunc, CallingLine, xsema, FindTask(NULL), \
595 FindTask(NULL)->tc_Node.ln_Name ? FindTask(NULL)->tc_Node.ln_Name : (char *) ""));
597 Result = AttemptSemaphoreShared(&xsema->Sema);
599 if (Result)
601 struct DebugSemaOwner *Owner;
603 d1(KPrintF("%s/%s/%ld: AttemptSemaphoreShared() succeeded\n", __FILE__, __FUNC__, __LINE__));
605 Owner = AllocVec(sizeof(struct DebugSemaOwner), MEMF_PUBLIC);
606 if (Owner)
608 Forbid();
609 Owner->OwnMode = OWNMODE_SHARED;
610 Owner->FileName = CallingFile;
611 Owner->Func = CallingFunc;
612 Owner->Line = CallingLine;
613 Owner->Proc = (struct Process *) FindTask(NULL);
614 AddHead(&xsema->OwnerList, &Owner->node);
615 Permit();
618 else
620 Result = DebugScalosAttemptSemaphore(xsema, CallingFile, CallingFunc, CallingLine);
623 d1(kprintf("%s/%s/%ld: End AttemptSemaphoreShared(%08lx) = %ld\n", \
624 CallingFile, CallingFunc, CallingLine, xsema, Result));
626 return Result;
629 #else /* DEBUG_SEMAPHORES */
631 #undef ScalosCreateSemaphore
632 #undef ScalosDeleteSemaphore
633 #undef ScalosInitSemaphore
634 #undef ScalosObtainSemaphore
635 #undef ScalosObtainSemaphoreShared
636 #undef ScalosReleaseSemaphore
637 #undef ScalosAttemptSemaphore
638 #undef ScalosAttemptSemaphoreShared
641 struct ScaWindowList *SCA_LockWindowList(LONG accessmode)
643 switch (accessmode)
645 case SCA_LockWindowList_Shared:
646 ObtainSemaphoreShared_Debug(&WinListSemaphore,
647 CallingFile, CallingFunc, CallingLine);
648 break;
649 case SCA_LockWindowList_Exclusiv:
650 ObtainSemaphore_Debug(&WinListSemaphore,
651 CallingFile, CallingFunc, CallingLine);
652 break;
653 default:
654 break;
657 return &winlist;
661 SCALOSSEMAPHORE *ScalosCreateSemaphore(void)
663 SCALOSSEMAPHORE *sema;
665 sema = AllocVec(sizeof(SCALOSSEMAPHORE), MEMF_PUBLIC | MEMF_CLEAR);
666 if (sema)
667 ScalosInitSemaphore(sema);
669 return sema;
673 void ScalosDeleteSemaphore(SCALOSSEMAPHORE *sema)
675 if (sema)
677 ScalosObtainSemaphore(sema);
678 Forbid();
679 ScalosReleaseSemaphore(sema);
680 FreeVec(sema);
681 Permit();
685 void ScalosInitSemaphore(struct ScalosSemaphore *xsema)
687 InitSemaphore(&xsema->Sema);
691 void ScalosObtainSemaphore(struct ScalosSemaphore *xsema)
693 ObtainSemaphore(&xsema->Sema);
697 void ScalosObtainSemaphoreShared(struct ScalosSemaphore *xsema)
699 ObtainSemaphoreShared(&xsema->Sema);
703 void ScalosReleaseSemaphore(struct ScalosSemaphore *xsema)
705 ReleaseSemaphore(&xsema->Sema);
709 ULONG ScalosAttemptSemaphore(struct ScalosSemaphore *xsema)
711 return AttemptSemaphore(&xsema->Sema);
715 ULONG ScalosAttemptSemaphoreShared(struct ScalosSemaphore *xsema)
717 return AttemptSemaphoreShared(&xsema->Sema)
718 || AttemptSemaphore(&xsema->Sema);
721 #endif /* DEBUG_SEMAPHORES */