Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
NAME
       ck_cohort -- generalized	interface for lock cohorts

LIBRARY
       Concurrency Kit (libck, -lck)

SYNOPSIS
       #include	<ck_cohort.h>

       CK_COHORT_PROTOTYPE(COHORT_NAME				  cohort_name,
	   LOCK_FXN   global_lock_method,    LOCK_FXN	 global_unlock_method,
	   LOCK_FXN local_lock_method, LOCK_FXN	local_unlock_method);

       CK_COHORT_TRYLOCK_PROTOTYPE(COHORT_NAME			  cohort_name,
	   LOCK_FXN   global_lock_method,    LOCK_FXN	 global_unlock_method,
	   BOOL_LOCK_FXN				 global_locked_method,
	   BOOL_LOCK_FXN  global_trylock_method,  LOCK_FXN  local_lock_method,
	   LOCK_FXN  local_unlock_method,  BOOL_LOCK_FXN  local_locked_method,
	   BOOL_LOCK_FXN local_trylock_method);

       CK_COHORT_INSTANCE(COHORT_NAME cohort_name);

       CK_COHORT_INIT(COHORT_NAME     cohort_name,     ck_cohort      *cohort,
	   void	*global_lock, void *local_lock,	unsigned int pass_limit);

       CK_COHORT_LOCK(COHORT_NAME      cohort_name,	ck_cohort     *cohort,
	   void	*global_context, void *local_context);

       CK_COHORT_UNLOCK(COHORT_NAME    cohort_name,	ck_cohort     *cohort,
	   void	*global_context, void *local_context);

       Where LOCK_FXN refers to	a method with the signature
       void(void *lock,	void *context)
       BOOL_LOCK_FXN refers to a method	with the signature
       bool(void *lock,	void *context)

       The context
       argument	 in each signature is used to pass along any additional	infor-
       mation that the lock might need for its lock, unlock and	trylock	 meth-
       ods.   The  values  for	this  argument	are  provided  to each call to
       CK_COHORT_LOCK(3),   CK_COHORT_UNLOCK(3),   CK_COHORT_LOCKED(3),	   and
       CK_COHORT_TRYLOCK(3)

DESCRIPTION
       ck_cohort.h  provides an	interface for defining lock cohorts with arbi-
       trary lock types.  Cohorts are a	mechanism for coordinating threads  on
       NUMA  architectures  in order to	reduce the frequency with which	a lock
       is passed between threads on different clusters.

       Before using a cohort, the user must define a cohort type using	either
       the  CK_COHORT_PROTOTYPE() or the CK_COHORT_TRYLOCK_PROTOTYPE() macros.
       These macros allow the user to specify the lock methods that they would
       like  the  cohort  to  use.    See   the	  CK_COHORT_PROTOTYPE(3)   and
       CK_COHORT_TRYLOCK_PROTOTYPE(3) man pages	for more details.

EXAMPLE
	     #include <stdlib.h>
	     #include <pthread.h>

	     #include <ck_pr.h>
	     #include <ck_cohort.h>
	     #include <ck_spinlock.h>

	     /*
	      *	Create cohort methods with signatures that match
	      *	the required signature
	      */
	     static void
	     ck_spinlock_lock_with_context(ck_spinlock_t *lock,	void *context)
	     {
		     (void)context;
		     ck_spinlock_lock(lock);
		     return;
	     }

	     static void
	     ck_spinlock_unlock_with_context(ck_spinlock_t *lock, void *context)
	     {
		     (void)context;
		     ck_spinlock_unlock(lock);
		     return;
	     }

	     static bool
	     ck_spinlock_locked_with_context(ck_spinlock_t *lock, void *context)
	     {
		     (void)context;
		     return ck_spinlock_locked(lock);
	     }

	     /*
	      *	define a cohort	type named "test_cohort" that will use
	      *	the above methods for both its global and local	locks
	      */
	     CK_COHORT_PROTOTYPE(test_cohort,
		     ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context,
		     ck_spinlock_lock_with_context, ck_spinlock_unlock_with_context, ck_spinlock_locked_with_context)

	     static ck_spinlock_t global_lock =	CK_SPINLOCK_INITIALIZER;
	     static unsigned int ready;

	     static void *
	     function(void *context)
	     {
		     CK_COHORT_INSTANCE(test_cohort) *cohort = context;

		     while (ready == 0);

		     while (ready > 0) {
			     /*
			      *	acquire	the cohort lock	before performing critical section.
			      *	note that we pass NULL for both	the global and local context
			      *	arguments because neither the lock nor unlock functions
			      *	will use them.
			      */
			     CK_COHORT_LOCK(test_cohort, cohort, NULL, NULL);

			     /*	perform	critical section */

			     /*	relinquish cohort lock */
			     CK_COHORT_UNLOCK(test_cohort, cohort, NULL, NULL);
		     }

		     return NULL;
	     }

	     int
	     main(void)
	     {
		     unsigned int nthr = 4;
		     unsigned int n_cohorts = 2;
		     unsigned int i;

		     /*	allocate 2 cohorts of the defined type */
		     CK_COHORT_INSTANCE(test_cohort) *cohorts =
			 calloc(n_cohorts, sizeof(CK_COHORT_INSTANCE(test_cohort)));

		     /*	create local locks to use with each cohort */
		     ck_spinlock_t *local_locks	=
			     calloc(n_cohorts, sizeof(ck_spinlock_t));

		     pthread_t *threads	=
			     calloc(nthr, sizeof(pthread_t));

		     /*	initialize each	of the cohorts before using them */
		     for (i = 0	; i < n_cohorts	; ++i) {
			     CK_COHORT_INIT(test_cohort, cohorts + i, &global_lock, local_locks	+ i,
				     CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT);
		     }

		     /*	start each thread and assign cohorts equally */
		     for (i = 0	; i < nthr ; ++i) {
			     pthread_create(threads + i, NULL, function, cohorts + (i %	n_cohorts));
		     }

		     ck_pr_store_uint(&ready, 1);
		     sleep(10);
		     ck_pr_store_uint(&ready, 0);

		     for (i = 0	; i < nthr ; ++i) {
			     pthread_join(threads[i], NULL);
		     }

		     return 0;
	     }

SEE ALSO
       CK_COHORT_PROTOTYPE(3),		       CK_COHORT_TRYLOCK_PROTOTYPE(3),
       CK_COHORT_INSTANCE(3),	CK_COHORT_INITIALIZER(3),   CK_COHORT_INIT(3),
       CK_COHORT_LOCK(3),	CK_COHORT_UNLOCK(3),	  CK_COHORT_LOCKED(3),
       CK_COHORT_TRYLOCK(3),

       Additional information available	at http://concurrencykit.org/

			      February 24, 2013.		  ck_cohort(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=ck_cohort&sektion=3&manpath=FreeBSD+Ports+14.3.quarterly>

home | help