RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 21-Feb-2009 19:20:49 Branch: HEAD Handle: 2009022118204701 Added files: rpm/rpmio yarn.c yarn.h Modified files: rpm CHANGES rpm/rpmio Makefile.am librpmio.vers Log: - jbj: yarn: add to rpmio. Summary: Revision Changes Path 1.2784 +1 -0 rpm/CHANGES 1.207 +4 -4 rpm/rpmio/Makefile.am 2.81 +11 -0 rpm/rpmio/librpmio.vers 2.1 +504 -0 rpm/rpmio/yarn.c 2.1 +164 -0 rpm/rpmio/yarn.h ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/CHANGES ============================================================================ $ cvs diff -u -r1.2783 -r1.2784 CHANGES --- rpm/CHANGES 19 Feb 2009 19:55:50 -0000 1.2783 +++ rpm/CHANGES 21 Feb 2009 18:20:47 -0000 1.2784 @@ -1,5 +1,6 @@ 5.2a2 -> 5.2a3: + - jbj: yarn: add to rpmio. - jbj: rpmz: stub in argv[0] processing to set operation mode. - jbj: rpmz: stub in RPMZ envvar option processing. - jbj: fix: eliminate a argvSplit() memory leak. @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/Makefile.am ============================================================================ $ cvs diff -u -r1.206 -r1.207 Makefile.am --- rpm/rpmio/Makefile.am 15 Feb 2009 13:55:33 -0000 1.206 +++ rpm/rpmio/Makefile.am 21 Feb 2009 18:20:48 -0000 1.207 @@ -57,8 +57,8 @@ $(RPMIO_LDADD_COMMON) pkgincdir = $(pkgincludedir)$(WITH_PATH_VERSIONED_SUFFIX) -pkginc_HEADERS = \ - mire.h rpmcb.h rpmio.h rpmlog.h rpmiotypes.h rpmmacro.h rpmpgp.h rpmsw.h +pkginc_HEADERS = mire.h yarn.h \ + rpmcb.h rpmio.h rpmlog.h rpmiotypes.h rpmmacro.h rpmpgp.h rpmsw.h noinst_HEADERS = \ argv.h ar.h cpio.h crc.h envvar.h fnmatch.h fts.h glob.h iosm.h \ md2.h md4.h rmd128.h rmd160.h rmd256.h rmd320.h sha224.h \ @@ -67,7 +67,7 @@ rpmgc.h rpmhash.h rpmhook.h rpmio_internal.h rpmkeyring.h rpmku.h \ rpmlua.h rpmmg.h rpmnss.h rpmsq.h rpmssl.h \ rpmio-stub.h rpmurl.h rpmuuid.h rpmxar.h \ - tar.h ugid.h + tar.h ugid.h yarn.h usrlibdir = $(libdir) usrlib_LTLIBRARIES = librpmio.la @@ -80,7 +80,7 @@ rpmbc.c rpmdav.c rpmgc.c rpmhash.c rpmhook.c rpmio.c rpmiob.c rpmio-stub.c \ rpmkeyring.c rpmku.c rpmlog.c rpmlua.c rpmmalloc.c rpmmg.c rpmnss.c rpmpgp.c \ rpmrpc.c rpmsq.c rpmssl.c rpmsw.c rpmuuid.c rpmxar.c \ - strcasecmp.c strtolocale.c tar.c url.c ugid.c + strcasecmp.c strtolocale.c tar.c url.c ugid.c yarn.c librpmio_la_LDFLAGS = -release $(LT_CURRENT).$(LT_REVISION) if HAVE_LD_VERSION_SCRIPT librpmio_la_LDFLAGS += -Wl,--version-script=$(srcdir)/librpmio.vers @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/librpmio.vers ============================================================================ $ cvs diff -u -r2.80 -r2.81 librpmio.vers --- rpm/rpmio/librpmio.vers 17 Feb 2009 19:39:25 -0000 2.80 +++ rpm/rpmio/librpmio.vers 21 Feb 2009 18:20:48 -0000 2.81 @@ -462,6 +462,17 @@ XurlLink; XurlNew; xzdio; + yarnJoin; + yarnJoinAll; + yarnLaunch; + yarnMem; + yarnNewLock; + yarnPeekLock; + yarnPossess; + yarnPrefix; + yarnRelease; + yarnTwist; + yarnWaitFor; local: *; }; @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/yarn.c ============================================================================ $ cvs diff -u -r0 -r2.1 yarn.c --- /dev/null 2009-02-21 19:19:45 +0100 +++ yarn.c 2009-02-21 19:20:49 +0100 @@ -0,0 +1,504 @@ +/* yarn.c -- generic thread operations implemented using pthread functions + * Copyright (C) 2008 Mark Adler + * Version 1.1 26 Oct 2008 Mark Adler + * For conditions of distribution and use, see copyright notice in yarn.h + */ + +/* Basic thread operations implemented using the POSIX pthread library. All + pthread references are isolated within this module to allow alternate + implementations with other thread libraries. See yarn.h for the description + of these operations. */ + +/* Version history: + 1.0 19 Oct 2008 First version + 1.1 26 Oct 2008 No need to set the stack size -- remove + Add yarn_abort() function for clean-up on error exit + */ + +/* for thread portability */ +#define _POSIX_PTHREAD_SEMANTICS +#define _REENTRANT + +/* external libraries and entities referenced */ +#include <stdio.h> /* fprintf(), stderr */ +#include <stdlib.h> /* exit(), malloc(), free(), NULL */ +/*...@-incondefs@*/ +#include <pthread.h> /* pthread_t, pthread_create(), pthread_join(), */ + /* pthread_attr_t, pthread_attr_init(), pthread_attr_destroy(), + PTHREAD_CREATE_JOINABLE, pthread_attr_setdetachstate(), + pthread_self(), pthread_equal(), + pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER, pthread_mutex_init(), + pthread_mutex_lock(), pthread_mutex_unlock(), pthread_mutex_destroy(), + pthread_cond_t, PTHREAD_COND_INITIALIZER, pthread_cond_init(), + pthread_cond_broadcast(), pthread_cond_wait(), pthread_cond_destroy() */ +/*...@=incondefs@*/ + +#include <errno.h> /* ENOMEM, EAGAIN, EINVAL */ + +#if defined(__LCLINT__) +/*...@-incondefs -protoparamma...@*/ +/*...@-exportheader@*/ +#ifdef NOTYET +extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROW + /*...@*/; +extern void (*__cancel_routine) (void *) + /*...@*/; +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + /*...@*/; +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + /*...@*/; +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + /*...@*/; +#endif + +extern pthread_t pthread_self(void) + /*...@*/; +extern int pthread_equal(pthread_t t1, pthread_t t2) + /*...@*/; + +extern int pthread_attr_init (pthread_attr_t *__attr) + __THROW __nonnull ((1)) + /*...@*/; +extern int pthread_attr_destroy (pthread_attr_t *__attr) + __THROW __nonnull ((1)) + /*...@*/; + +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) + __THROW __nonnull ((1)) + /*...@*/; + +extern int pthread_create(/*...@out@*/ pthread_t *__restrict __newthread, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine)(void*), + void *__restrict arg) __THROW __nonnull ((1, 3)) + /*...@modifies *__newthread @*/; +extern int pthread_join(pthread_t thread, /*...@out@*/ void **value_ptr) + /*...@modifies *value_ptr @*/; + +extern int pthread_mutex_destroy(pthread_mutex_t *mutex) + /*...@modifies *mutex @*/; +extern int pthread_mutex_init(/*...@out@*/ pthread_mutex_t *restrict mutex, + /*...@null@*/ const pthread_mutexattr_t *restrict attr) + /*...@globals errno, internalState @*/ + /*...@modifies *mutex, errno, internalState @*/; + +extern int pthread_mutex_lock(pthread_mutex_t *mutex) + /*...@globals errno @*/ + /*...@modifies *mutex, errno @*/; +extern int pthread_mutex_trylock(pthread_mutex_t *mutex) + /*...@globals errno @*/ + /*...@modifies *mutex, errno @*/; +extern int pthread_mutex_unlock(pthread_mutex_t *mutex) + /*...@globals errno @*/ + /*...@modifies *mutex, errno @*/; + +extern int pthread_cond_destroy(pthread_cond_t *cond) + /*...@modifies *cond @*/; +extern int pthread_cond_init(/*...@out@*/ pthread_cond_t *restrict cond, + const pthread_condattr_t *restrict attr) + /*...@globals errno, internalState @*/ + /*...@modifies *cond, errno, internalState @*/; + +extern int pthread_cond_timedwait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex, + const struct timespec *restrict abstime) + /*...@modifies *cond, *mutex @*/; +extern int pthread_cond_wait(pthread_cond_t *restrict cond, + pthread_mutex_t *restrict mutex) + /*...@modifies *cond, *mutex @*/; +extern int pthread_cond_broadcast(pthread_cond_t *cond) + /*...@globals errno, internalState @*/ + /*...@modifies *cond, errno, internalState @*/; +extern int pthread_cond_signal(pthread_cond_t *cond) + /*...@globals errno, internalState @*/ + /*...@modifies *cond, errno, internalState @*/; + +extern int pthread_cancel (pthread_t __th) + /*...@*/; + +/*...@=exportheader@*/ +/*...@=incondefs =protoparamma...@*/ +#endif /* __LCLINT__ */ + +/* interface definition */ +#include "yarn.h" + +/* error handling external globals, resettable by application */ +/*...@unchecked@*/ /*...@observer@*/ +const char *yarnPrefix = "yarn"; +/*...@-nullassign@*/ +void (*yarnAbort)(int) = NULL; +/*...@=nullassign@*/ + + +/* immediately exit -- use for errors that shouldn't ever happen */ +/*...@exits@*/ +static void fail(int err) + /*...@globals fileSystem, internalState @*/ + /*...@modifies fileSystem, internalState @*/ +{ + fprintf(stderr, "%s: %s (%d) -- aborting\n", yarnPrefix, + err == ENOMEM ? "out of memory" : "internal pthread error", err); + if (yarnAbort != NULL) + yarnAbort(err); + exit(err == ENOMEM || err == EAGAIN ? err : EINVAL); +} + +/* memory handling routines provided by user -- if none are provided, malloc() + and free() are used, which are therefore assumed to be thread-safe */ +typedef void *(*malloc_t)(size_t); +typedef void (*free_t)(void *); +#if defined(__LCLINT__) +static void *(*my_malloc_f)(size_t nb) + /*...@*/ + = malloc; +static void (*my_free)(/*...@only@*/ void * p) + /*...@modifies p @*/ + = free; +#else +static malloc_t my_malloc_f = malloc; +static free_t my_free = free; +#endif + +/* use user-supplied allocation routines instead of malloc() and free() */ +/*...@-mustmod @*/ +void yarnMem(malloc_t lease, free_t vacate) + /*...@globals my_malloc_f, my_free @*/ + /*...@modifies my_malloc_f, my_free @*/ +{ + my_malloc_f = lease; + my_free = vacate; +} +/*...@=mustmod @*/ + +/* memory allocation that cannot fail (from the point of view of the caller) */ +static void *my_malloc(size_t size) + /*...@globals fileSystem, internalState @*/ + /*...@modifies fileSystem, internalState @*/ +{ + void *block; + + if ((block = my_malloc_f(size)) == NULL) + fail(ENOMEM); + return block; +} + +/* -- lock functions -- */ + +struct yarnLock_s { + pthread_mutex_t mutex; + pthread_cond_t cond; + long value; +}; + +yarnLock yarnNewLock(long initial) +{ + int ret; + yarnLock bolt; + + bolt = my_malloc(sizeof(*bolt)); + if ((ret = pthread_mutex_init(&(bolt->mutex), NULL)) || + (ret = pthread_cond_init(&(bolt->cond), NULL))) + fail(ret); + bolt->value = initial; + return bolt; +} + +void yarnPossess(yarnLock bolt) +{ + int ret; + + if ((ret = pthread_mutex_lock(&(bolt->mutex))) != 0) + fail(ret); +} + +void yarnRelease(yarnLock bolt) +{ + int ret; + + if ((ret = pthread_mutex_unlock(&(bolt->mutex))) != 0) + fail(ret); +} + +void yarnTwist(yarnLock bolt, yarnTwistOP op, long val) +{ + int ret; + + if (op == TO) + bolt->value = val; + else if (op == BY) + bolt->value += val; + if ((ret = pthread_cond_broadcast(&(bolt->cond))) || + (ret = pthread_mutex_unlock(&(bolt->mutex)))) + fail(ret); +} + +#define until(a) while(!(a)) + +void yarnWaitFor(yarnLock bolt, yarnWaitOP op, long val) +{ + int ret; + +/*...@-infloops@*/ /* XXX splint can't see non-annotated effects */ + switch (op) { + case TO_BE: + until (bolt->value == val) + if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0) + fail(ret); + break; + case NOT_TO_BE: + until (bolt->value != val) + if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0) + fail(ret); + break; + case TO_BE_MORE_THAN: + until (bolt->value > val) + if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0) + fail(ret); + break; + case TO_BE_LESS_THAN: + until (bolt->value < val) + if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0) + fail(ret); + } +/*...@=infloops@*/ +} + +long yarnPeekLock(yarnLock bolt) +{ + return bolt->value; +} + +void yarnFreeLock(yarnLock bolt) +{ + int ret; + if ((ret = pthread_cond_destroy(&(bolt->cond))) || + (ret = pthread_mutex_destroy(&(bolt->mutex)))) + fail(ret); + my_free(bolt); +} + +/* -- thread functions (uses lock functions above) -- */ + +struct yarnThread_s { + pthread_t id; + int done; /* true if this thread has exited */ +/*...@dependent@*/ /*...@null@*/ + yarnThread next; /* for list of all launched threads */ +}; + +/* list of threads launched but not joined, count of threads exited but not + joined (incremented by yarnIgnition() just before exiting) */ +/*...@unchecked@*/ +static struct yarnLock_s threads_lock = { + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_COND_INITIALIZER, + 0 /* number of threads exited but not joined */ +}; +/*...@unchecked@*/ /*...@owned@*/ /*...@null@*/ +static yarnThread threads = NULL; /* list of extant threads */ + +/* structure in which to pass the probe and its payload to yarnIgnition() */ +struct capsule { + void (*probe)(void *) + /*...@*/; + void * payload; +}; + +/* mark the calling thread as done and alert yarnJoinAll() */ +static void yarnReenter(void * dummy) + /*...@globals threads, threads_lock, fileSystem, internalState @*/ + /*...@modifies threads, threads_lock, fileSystem, internalState @*/ +{ + yarnThread match; + yarnThread *prior; + pthread_t me; + + /* find this thread in the threads list by matching the thread id */ + me = pthread_self(); + yarnPossess(&(threads_lock)); + prior = &(threads); + while ((match = *prior) != NULL) { + if (pthread_equal(match->id, me)) + break; + prior = &(match->next); + } + if (match == NULL) + fail(EINVAL); + + /* mark this thread as done and move it to the head of the list */ + match->done = 1; + if (threads != match) { + *prior = match->next; + match->next = threads; + threads = match; + } + + /* update the count of threads to be joined and alert yarnJoinAll() */ + yarnTwist(&(threads_lock), BY, 1); +} + +/* all threads go through this routine so that just before the thread exits, + it marks itself as done in the threads list and alerts yarnJoinAll() so that + the thread resources can be released -- use cleanup stack so that the + marking occurs even if the thread is cancelled */ +/*...@null@*/ +static void * yarnIgnition(/*...@only@*/ void * arg) + /*...@*/ +{ + struct capsule *capsule = arg; + + /* run yarnReenter() before leaving */ +/*...@-moduncon -noeffectuncon @*/ + pthread_cleanup_push(yarnReenter, NULL); +/*...@=moduncon =noeffectuncon @*/ + + /* execute the requested function with argument */ +/*...@-noeffectuncon@*/ + capsule->probe(capsule->payload); +/*...@=noeffectuncon@*/ + my_free(capsule); + + /* mark this thread as done and let yarnJoinAll() know */ +/*...@-moduncon -noeffect -noeffectuncon @*/ + pthread_cleanup_pop(1); +/*...@=moduncon =noeffect =noeffectuncon @*/ + + /* exit thread */ + return NULL; +} + +/* not all POSIX implementations create threads as joinable by default, so that + is made explicit here */ +yarnThread yarnLaunch(void (*probe)(void *), void * payload) + /*...@globals threads @*/ + /*...@modifies threads @*/ +{ + int ret; + yarnThread th; + struct capsule * capsule; + pthread_attr_t attr; + + /* construct the requested call and argument for the yarnIgnition() routine + (allocated instead of automatic so that we're sure this will still be + there when yarnIgnition() actually starts up -- yarnIgnition() will free this + allocation) */ + capsule = my_malloc(sizeof(struct capsule)); + capsule->probe = probe; +/*...@-mustfreeonly@*/ + capsule->payload = payload; +/*...@=mustfreeonly@*/ + + /* assure this thread is in the list before yarnJoinAll() or yarnIgnition() looks + for it */ + yarnPossess(&(threads_lock)); + + /* create the thread and call yarnIgnition() from that thread */ + th = my_malloc(sizeof(*th)); + if ((ret = pthread_attr_init(&attr)) || + (ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) || + (ret = pthread_create(&(th->id), &attr, yarnIgnition, capsule)) || + (ret = pthread_attr_destroy(&attr))) + fail(ret); + + /* put the thread in the threads list for yarnJoinAll() */ + th->done = 0; + th->next = threads; + threads = th; + yarnRelease(&(threads_lock)); +/*...@-dependenttrans -globstate -mustfreefresh @*/ /* XXX what frees capsule?!? */ + return th; +/*...@=dependenttrans =globstate =mustfreefresh @*/ +} + +void yarnJoin(yarnThread ally) + /*...@globals threads, threads_lock @*/ + /*...@modifies threads, threads_lock @*/ +{ + yarnThread match; + yarnThread *prior; + int ret; + + /* wait for thread to exit and return its resources */ + if ((ret = pthread_join(ally->id, NULL)) != 0) + fail(ret); + + /* find the thread in the threads list */ + yarnPossess(&(threads_lock)); + prior = &(threads); + while ((match = *prior) != NULL) { + if (match == ally) + break; + prior = &(match->next); + } + if (match == NULL) + fail(EINVAL); + + /* remove thread from list and update exited count, free thread */ + if (match->done) + threads_lock.value--; + *prior = match->next; + yarnRelease(&(threads_lock)); + my_free(ally); +} + +/* This implementation of yarnJoinAll() only attempts to join threads that have + announced that they have exited (see yarnIgnition()). When there are many + threads, this is faster than waiting for some random thread to exit while a + bunch of other threads have already exited. */ +int yarnJoinAll(void) + /*...@globals threads, threads_lock @*/ + /*...@modifies threads, threads_lock @*/ +{ + yarnThread match; + yarnThread *prior; + int ret; + int count; + + /* grab the threads list and initialize the joined count */ + count = 0; + yarnPossess(&(threads_lock)); + + /* do until threads list is empty */ + while (threads != NULL) { + /* wait until at least one thread has reentered */ + yarnWaitFor(&(threads_lock), NOT_TO_BE, 0); + + /* find the first thread marked done (should be at or near the top) */ + prior = &(threads); + while ((match = *prior) != NULL) { + if (match->done) + break; + prior = &(match->next); + } + if (match == NULL) + fail(EINVAL); + + /* join the thread (will be almost immediate), remove from the threads + list, update the reenter count, and free the thread */ + if ((ret = pthread_join(match->id, NULL)) != 0) + fail(ret); + threads_lock.value--; + *prior = match->next; + my_free(match); + count++; + } + + /* let go of the threads list and return the number of threads joined */ + yarnRelease(&(threads_lock)); +/*...@-globstate@*/ + return count; +/*...@=globstate@*/ +} + +/* cancel and join the thread -- the thread will cancel when it gets to a file + operation, a sleep or pause, or a condition wait */ +void yarnDestruct(yarnThread off_course) +{ + int ret; + + if ((ret = pthread_cancel(off_course->id)) != 0) + fail(ret); + yarnJoin(off_course); +} @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/yarn.h ============================================================================ $ cvs diff -u -r0 -r2.1 yarn.h --- /dev/null 2009-02-21 19:19:45 +0100 +++ yarn.h 2009-02-21 19:20:49 +0100 @@ -0,0 +1,164 @@ +/* yarn.h -- generic interface for thread operations + * Copyright (C) 2008 Mark Adler + * Version 1.1 26 Oct 2008 Mark Adler + */ + +/* + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler + mad...@alumni.caltech.edu + */ + +/* Basic thread operations + + This interface isolates the local operating system implementation of threads + from the application in order to facilitate platform independent use of + threads. All of the implementation details are deliberately hidden. + + Assuming adequate system resources and proper use, none of these functions + can fail. As a result, any errors encountered will cause an exit() to be + executed. + + These functions allow the simple launching and joining of threads, and the + locking of objects and synchronization of changes of objects. The latter is + implemented with a single lock type that contains an integer value. The + value can be ignored for simple exclusive access to an object, or the value + can be used to signal and wait for changes to an object. + + -- Arguments -- + + thread *thread; identifier for launched thread, used by join + void probe(void *); pointer to function "probe", run when thread starts + void *payload; single argument passed to the probe function + yarnLock lock; a lock with a value -- used for exclusive access to + an object and to synchronize threads waiting for + changes to an object + long val; value to set lock, increment lock, or wait for + int n; number of threads joined + + -- Thread functions -- + + thread = yarnLaunch(probe, payload) - launch a thread -- exit via probe() return + yarnJoin(thread) - join a thread and by joining end it, waiting for the thread + to exit if it hasn't already -- will free the resources allocated by + yarnLaunch() (don't try to join the same thread more than once) + n = yarnJoinAll() - join all threads launched by yarnLaunch() that are not joined + yet and free the resources allocated by the launches, usually to clean + up when the thread processing is done -- yarnJoinAll() returns an int with + the count of the number of threads joined (yarnJoinAll() should only be + called from the main thread, and should only be called after any calls + of yarnJoin() have completed) + yarnDestruct(thread) - terminate the thread in mid-execution and join it + (depending on the implementation, the termination may not be immediate, + but may wait for the thread to execute certain thread or file i/o + operations) + + -- Lock functions -- + + lock = yarnNewLock(val) - create a new lock with initial value val (lock is + created in the released state) + yarnPossess(lock) - acquire exclusive possession of a lock, waiting if necessary + yarnTwist(lock, [TO | BY], val) - set lock to or increment lock by val, signal + all threads waiting on this lock and then release the lock -- must + possess the lock before calling (twist releases, so don't do a + yarnRelease() after a yarnTwist() on the same lock) + yarnWaitFor(lock, [TO_BE | NOT_TO_BE | TO_BE_MORE_THAN | TO_BE_LESS_THAN], val) + - wait on lock value to be, not to be, be greater than, or be less than + val -- must possess the lock before calling, will possess the lock on + return but the lock is released while waiting to permit other threads + to use yarnTwist() to change the value and signal the change (so make sure + that the object is in a usable state when waiting) + yarnRelease(lock) - release a possessed lock (do not try to release a lock that + the current thread does not possess) + val = yarnPeekLock(lock) - return the value of the lock (assumes that lock is + already possessed, no possess or release is done by yarnPeekLock()) + yarnFreeLock(lock) - free the resources allocated by yarnNewLock() (application + must assure that the lock is released before calling yarnFreeLock()) + + -- Memory allocation --- + + yarnMem(better_malloc, better_free) - set the memory allocation and free + routines for use by the yarn routines where the supplied routines have + the same interface and operation as malloc() and free(), and may be + provided in order to supply thread-safe memory allocation routines or + for any other reason -- by default malloc() and free() will be used + + -- Error control -- + + yarnPrefix - a char pointer to a string that will be the prefix for any error + messages that these routines generate before exiting -- if not changed + by the application, "yarn" will be used + yarnAbort - an external function that will be executed when there is an + internal yarn error, due to out of memory or misuse -- this function + may exit to abort the application, or if it returns, the yarn error + handler will exit (set to NULL by default for no action) + */ + +/*...@unchecked@*/ /*...@observer@*/ +extern const char *yarnPrefix; +/*...@mayexit@*/ +extern void (*yarnAbort)(int) + /*...@globals internalState @*/ + /*...@modifies internalState @*/; + +/*...@-globuse@*/ +void yarnMem(void *(*)(size_t), void (*)(void *)) + /*...@globals internalState @*/ + /*...@modifies internalState @*/; +/*...@=globuse@*/ + +typedef struct yarnThread_s * yarnThread; +/*...@only@*/ +yarnThread yarnLaunch(void (*probe)(void *), void *payload) + /*...@globals fileSystem, internalState @*/ + /*...@modifies fileSystem, internalState @*/; +void yarnJoin(/*...@only@*/ yarnThread ally) + /*...@globals fileSystem, internalState @*/ + /*...@modifies ally, fileSystem, internalState @*/; +int yarnJoinAll(void) + /*...@globals fileSystem, internalState @*/ + /*...@modifies fileSystem, internalState @*/; +void yarnDestruct(/*...@only@*/ yarnThread off_course) + /*...@globals fileSystem, internalState @*/ + /*...@modifies off_course, fileSystem, internalState @*/; + +typedef struct yarnLock_s * yarnLock; +yarnLock yarnNewLock(long) + /*...@globals fileSystem, internalState @*/ + /*...@modifies fileSystem, internalState @*/; +void yarnPossess(yarnLock bolt) + /*...@globals fileSystem, internalState @*/ + /*...@modifies bolt, fileSystem, internalState @*/; +void yarnRelease(yarnLock bolt) + /*...@globals fileSystem, internalState @*/ + /*...@modifies bolt, fileSystem, internalState @*/; +typedef enum yarnTwistOP_e { TO, BY } yarnTwistOP; +void yarnTwist(yarnLock bolt, yarnTwistOP op, long) + /*...@globals fileSystem, internalState @*/ + /*...@modifies bolt, fileSystem, internalState @*/; +typedef enum yarnWaitOP_e { + TO_BE, /* or */ NOT_TO_BE, /* that is the question */ + TO_BE_MORE_THAN, TO_BE_LESS_THAN } yarnWaitOP; +void yarnWaitFor(yarnLock bolt, yarnWaitOP op, long) + /*...@globals fileSystem, internalState @*/ + /*...@modifies bolt, fileSystem, internalState @*/; +long yarnPeekLock(yarnLock bolt) + /*...@*/; +void yarnFreeLock(/*...@only@*/ yarnLock bolt) + /*...@globals fileSystem, internalState @*/ + /*...@modifies bolt, fileSystem, internalState @*/; @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org