Path: utzoo!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!ukc!slxsys!ibmpcug!duncanb From: duncanb@ibmpcug.co.uk (D G Booth) Newsgroups: comp.os.os2.programmer,connect.audit Subject: Re: Making a non exclusive semaphore (like on Unix) Keywords: semaphore, counter, exclusive Message-ID: <1991Mar12.152033.11880@ibmpcug.co.uk> Date: 12 Mar 91 15:20:33 GMT Organization: The IBM PC User Group, UK. Lines: 104 Christophe Wolfhugel asks whether OS/2 had any mechanism similar to the classic counting semaphores. There is no such mechanism built-in to OS/2, but I have used the code below quite successfully. The code defines a new structure type COUNTSEM which is a counting semaphore, and functions P and V that operate on it. P decrements the counter, but blocks if the counter is 0 until it is non-zero. V increments the counter (and unblocks any blocked threads). The code can be in an application managing mutual exclusion between threads. It may also be in a DLL to manage semaphores between processes, but in this case the MutualExclusion semaphore, and the COUNTSEM structures should all be put in shared memory. Duncan Booth ======= File: SEM.H ============ typedef struct COUNTSEM { long countSem; USHORT count; } COUNTSEM, far *PCOUNTSEM; void P (PCOUNTSEM s); /* Wait till non-zero then decrement. */ BOOL P_timeout (PCOUNTSEM s, LONG timeout); /* as P - may time out. */ void V (PCOUNTSEM s); /* Increment */ ======== End of SEM.H ========== ======= File: SEM.C ============ /* * Useful code using semaphores. * * Author: Duncan Booth */ #define INCL_DOSPROCESS #include #include "sem.h" /* * This semaphore is local to this file. It is used to control requests * to the counting semaphore structures. */ static long MutualExclusion = 0L; #define GET_SEM() (DosSemRequest (&MutualExclusion, SEM_INDEFINITE_WAIT)) #define RLS_SEM() (DosSemClear (&MutualExclusion)) void P (PCOUNTSEM s) { int blocked=1; while (blocked) { DosSemWait (&s->countSem, SEM_INDEFINITE_WAIT); /* wait til maybe ok */ GET_SEM(); if (s->count == 0) /* not ready yet */ DosSemSet (&s->countSem); /* set up block */ else { s->count--; /* decrement count */ blocked = 0; /* set up loop exit */ } RLS_SEM(); } } BOOL P_timeout (PCOUNTSEM s, LONG timeout) { int blocked=1; while (blocked == 1) { if (DosSemWait (&s->countSem, timeout) != 0) return FALSE; /* wait til maybe ok */ if (GET_SEM() != 0) return FALSE; if (s->count == 0) /* not ready yet */ DosSemSet (&s->countSem); /* set up block */ else { s->count--; /* decrement count */ blocked = 0; /* set up loop exit */ } RLS_SEM(); } return TRUE; } void V (PCOUNTSEM s) { GET_SEM(); /* mutual excl */ s->count++; /* increment count */ DosSemClear (&s->countSem); /* free waiters */ RLS_SEM(); /* mutual excl */ } ======== End of SEM.C ========== -- Automatic Disclaimer: The views expressed above are those of the author alone and may not represent the views of the IBM PC User Group. -- Duncan Booth, RCP Ltd. Didcot, Oxon, UK duncanb@ibmpcug.co.uk Bix: jrichards