summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c105
1 files changed, 84 insertions, 21 deletions
diff --git a/misc.c b/misc.c
index b3c5246..1b558f4 100644
--- a/misc.c
+++ b/misc.c
@@ -8,39 +8,102 @@
#include "pthread.h"
#include "implement.h"
+/*
+ * Code contributed by John E. Bossom <JEB>.
+ */
+
int
-pthread_once(pthread_once_t *once_control,
- void (*init_routine)(void))
+pthread_once (
+ pthread_once_t * once_control,
+ void (*init_routine) (void)
+)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * If any thread in a process with a once_control parameter
+ * makes a call to pthread_once(), the first call will summon
+ * the init_routine(), but subsequent calls will not. The
+ * once_control parameter determines whether the associated
+ * initialization routine has been called. The init_routine()
+ * is complete upon return of pthread_once().
+ * This function guarantees that one and only one thread
+ * executes the initialization routine, init_routine when
+ * access is controlled by the pthread_once_t control
+ * key.
+ *
+ * PARAMETERS
+ * once_control
+ * pointer to an instance of pthread_once_t
+ *
+ * init_routine
+ * pointer to an initialization routine
+ *
+ *
+ * DESCRIPTION
+ * See above.
+ *
+ * RESULTS
+ * 0 success,
+ * EINVAL once_control or init_routine is NULL
+ *
+ * ------------------------------------------------------
+ */
{
- /* A flag, allocated per invocation, that indicates if the atomic
- test-and-set occured. */
- unsigned short flag = 0;
+ int result;
if (once_control == NULL || init_routine == NULL)
{
- return EINVAL;
- }
- /* An atomic test-and-set of the "once" flag. */
- pthread_mutex_lock(&once_control->lock);
- if (once_control->flag == 0)
+ result = EINVAL;
+ goto FAIL0;
+
+ }
+ else
{
- flag = once_control->flag = 1;
+ result = 0;
}
- pthread_mutex_unlock(&once_control->lock);
- if (flag)
+ if (!once_control->done)
{
- /* Run the init routine. */
- init_routine();
+ if (InterlockedIncrement (&(once_control->started)) == 0)
+ {
+ /*
+ * First thread to increment the started variable
+ */
+ (*init_routine) ();
+ once_control->done = TRUE;
+
+ }
+ else
+ {
+ /*
+ * Block until other thread finishes executing the onceRoutine
+ */
+ while (!(once_control->done))
+ {
+ /*
+ * The following gives up CPU cycles without pausing
+ * unnecessarily
+ */
+ Sleep (0);
+ }
+ }
}
-
- return 0;
-}
-/*
- * Code contributed by John E. Bossom <JEB>.
- */
+ /*
+ * Fall through Intentionally
+ */
+
+ /*
+ * ------------
+ * Failure Code
+ * ------------
+ */
+FAIL0:
+ return (result);
+
+} /* pthread_once */
+
pthread_t
pthread_self (void)