interface: Made ck_cohort interface more flexible for custom types

ck_pring
Brendon Scheinman 12 years ago
parent 27d841d300
commit 803073b024

@ -37,12 +37,17 @@
#define CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT 10 #define CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT 10
#define CK_COHORT_INSTANCE(N) ck_cohort_##N #define CK_COHORT_NAME(N) ck_cohort_##N
#define CK_COHORT_INSTANCE(N) struct CK_COHORT_NAME(N)
#define CK_COHORT_INIT(N, C, GL, LL) ck_cohort_##N##_init(C, GL, LL)
#define CK_COHORT_LOCK(N, C, GC, LC) ck_cohort_##N##_lock(C, GC, LC)
#define CK_COHORT_UNLOCK(N, C, GC, LC) ck_cohort_##N##_unlock(C, GC, LC)
#define CK_COHORT_PROTOTYPE(N, TG, TL) \ #define CK_COHORT_PROTOTYPE(N, GT, GL, GU, LT, LL, LU) \
struct CK_COHORT_INSTANCE(N) { \ \
TG *global_lock; \ struct CK_COHORT_NAME(N) { \
TL *local_lock; \ GT *global_lock; \
LT *local_lock; \
unsigned int release_state; \ unsigned int release_state; \
unsigned int waiting_threads; \ unsigned int waiting_threads; \
unsigned int acquire_count; \ unsigned int acquire_count; \
@ -51,7 +56,7 @@
\ \
CK_CC_INLINE static void \ CK_CC_INLINE static void \
ck_cohort_##N##_init(struct ck_cohort_##N *cohort, \ ck_cohort_##N##_init(struct ck_cohort_##N *cohort, \
TG *global_lock, TL *local_lock) \ GT *global_lock, LT *local_lock) \
{ \ { \
ck_pr_store_ptr(&cohort->global_lock, global_lock); \ ck_pr_store_ptr(&cohort->global_lock, global_lock); \
ck_pr_store_ptr(&cohort->local_lock, local_lock); \ ck_pr_store_ptr(&cohort->local_lock, local_lock); \
@ -65,14 +70,15 @@
} \ } \
\ \
CK_CC_INLINE static void \ CK_CC_INLINE static void \
ck_cohort_##N##_lock(struct ck_cohort_##N *cohort) \ ck_cohort_##N##_lock(CK_COHORT_INSTANCE(N) *cohort, \
void *global_context, void *local_context) \
{ \ { \
ck_pr_inc_uint(&cohort->waiting_threads); \ ck_pr_inc_uint(&cohort->waiting_threads); \
TL##_lock(cohort->local_lock); \ LL(cohort->local_lock, local_context); \
ck_pr_dec_uint(&cohort->waiting_threads); \ ck_pr_dec_uint(&cohort->waiting_threads); \
\ \
if (cohort->release_state == CK_COHORT_RELEASE_STATE_GLOBAL) { \ if (cohort->release_state == CK_COHORT_RELEASE_STATE_GLOBAL) { \
TG##_lock(cohort->global_lock); \ GL(cohort->global_lock, global_context); \
cohort->release_state = CK_COHORT_RELEASE_STATE_LOCAL; \ cohort->release_state = CK_COHORT_RELEASE_STATE_LOCAL; \
} \ } \
\ \
@ -82,19 +88,20 @@
} \ } \
\ \
CK_CC_INLINE static void \ CK_CC_INLINE static void \
ck_cohort_##N##_unlock(struct ck_cohort_##N *cohort) \ ck_cohort_##N##_unlock(CK_COHORT_INSTANCE(N) *cohort, \
void *global_context, void *local_context) \
{ \ { \
if (ck_pr_load_uint(&cohort->waiting_threads) > 0 \ if (ck_pr_load_uint(&cohort->waiting_threads) > 0 \
&& cohort->acquire_count < cohort->local_pass_limit) { \ && cohort->acquire_count < cohort->local_pass_limit) { \
cohort->release_state = CK_COHORT_RELEASE_STATE_LOCAL; \ cohort->release_state = CK_COHORT_RELEASE_STATE_LOCAL; \
} else { \ } else { \
TG##_unlock(cohort->global_lock); \ GU(cohort->global_lock, global_context); \
cohort->release_state = CK_COHORT_RELEASE_STATE_GLOBAL; \ cohort->release_state = CK_COHORT_RELEASE_STATE_GLOBAL; \
cohort->acquire_count = 0; \ cohort->acquire_count = 0; \
} \ } \
\ \
ck_pr_fence_memory(); \ ck_pr_fence_memory(); \
TL##_unlock(cohort->local_lock); \ LU(cohort->local_lock, local_context); \
\ \
return; \ return; \
} }

@ -57,11 +57,24 @@ static unsigned int barrier;
int critical __attribute__((aligned(64))); int critical __attribute__((aligned(64)));
typedef ck_spinlock_fas_t ck_spinlock_fas; static void
typedef ck_spinlock_ticket_t ck_spinlock_ticket; ck_spinlock_ticket_lock_with_context(ck_spinlock_ticket_t *lock, void *context)
CK_COHORT_PROTOTYPE(fas_fas, ck_spinlock_ticket, ck_spinlock_ticket) {
static struct ck_cohort_fas_fas *cohorts; (void)context;
static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER; ck_spinlock_ticket_lock(lock);
}
static void
ck_spinlock_ticket_unlock_with_context(ck_spinlock_ticket_t *lock, void *context)
{
(void)context;
ck_spinlock_ticket_unlock(lock);
}
CK_COHORT_PROTOTYPE(ticket_ticket,
ck_spinlock_ticket_t, ck_spinlock_ticket_lock_with_context, ck_spinlock_ticket_unlock_with_context,
ck_spinlock_ticket_t, ck_spinlock_ticket_lock_with_context, ck_spinlock_ticket_unlock_with_context)
static CK_COHORT_INSTANCE(ticket_ticket) *cohorts;
static ck_spinlock_ticket_t global_ticket_lock = CK_SPINLOCK_TICKET_INITIALIZER; static ck_spinlock_ticket_t global_ticket_lock = CK_SPINLOCK_TICKET_INITIALIZER;
struct block { struct block {
@ -76,7 +89,7 @@ fairness(void *null)
volatile int j; volatile int j;
long int base; long int base;
unsigned int core; unsigned int core;
struct ck_cohort_fas_fas *cohort; CK_COHORT_INSTANCE(ticket_ticket) *cohort;
if (aff_iterate_core(&a, &core)) { if (aff_iterate_core(&a, &core)) {
perror("ERROR: Could not affine thread"); perror("ERROR: Could not affine thread");
@ -91,16 +104,15 @@ fairness(void *null)
while (ck_pr_load_uint(&barrier) != nthr); while (ck_pr_load_uint(&barrier) != nthr);
while (ready) { while (ready) {
ck_cohort_fas_fas_lock(cohort); CK_COHORT_LOCK(ticket_ticket, cohort, NULL, NULL);
fprintf(stderr, "lock acquired by thread %i\n", i);
count[i].value++; count[i].value++;
if (critical) { if (critical) {
base = common_lrand48() % critical; base = common_lrand48() % critical;
for (j = 0; j < base; j++); for (j = 0; j < base; j++);
} }
ck_cohort_fas_fas_unlock(cohort); CK_COHORT_UNLOCK(ticket_ticket, cohort, NULL, NULL);
} }
return (NULL); return (NULL);
@ -145,7 +157,7 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
cohorts = malloc(sizeof(struct ck_cohort_fas_fas) * n_cohorts); cohorts = malloc(sizeof(CK_COHORT_INSTANCE(ticket_ticket)) * n_cohorts);
if (cohorts == NULL) { if (cohorts == NULL) {
ck_error("ERROR: Could not allocate cohort structures\n"); ck_error("ERROR: Could not allocate cohort structures\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -175,7 +187,7 @@ main(int argc, char *argv[])
fprintf(stderr, "Creating cohorts..."); fprintf(stderr, "Creating cohorts...");
for (i = 0 ; i < n_cohorts ; i++) { for (i = 0 ; i < n_cohorts ; i++) {
ck_cohort_fas_fas_init(cohorts + i, &global_ticket_lock, local_fas_locks + i); CK_COHORT_INIT(ticket_ticket, cohorts + i, &global_ticket_lock, local_fas_locks + i);
} }
fprintf(stderr, "done\n"); fprintf(stderr, "done\n");

@ -1,10 +1,24 @@
#define LOCK_NAME "ck_cohort" #define LOCK_NAME "ck_cohort"
#define LOCK_DEFINE\ #define LOCK_DEFINE\
typedef ck_spinlock_fas_t ck_spinlock_fas;\ static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;\
static ck_spinlock_fas global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;\ static ck_spinlock_fas_t local_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;\
static ck_spinlock_fas local_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;\ static void\
CK_COHORT_PROTOTYPE(fas_fas, ck_spinlock_fas, ck_spinlock_fas)\ ck_spinlock_fas_lock_with_context(ck_spinlock_fas_t *lock, void *context)\
static struct ck_cohort_fas_fas CK_CC_CACHELINE cohort = CK_COHORT_INITIALIZER {\
#define LOCK_INIT ck_cohort_fas_fas_init(&cohort, &global_fas_lock, &local_fas_lock) (void)context;\
#define LOCK ck_cohort_fas_fas_lock(&cohort) ck_spinlock_fas_lock(lock);\
#define UNLOCK ck_cohort_fas_fas_unlock(&cohort) }\
\
static void\
ck_spinlock_fas_unlock_with_context(ck_spinlock_fas_t *lock, void *context)\
{\
(void)context;\
ck_spinlock_fas_unlock(lock);\
}\
CK_COHORT_PROTOTYPE(fas_fas,\
ck_spinlock_fas_t, ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context,\
ck_spinlock_fas_t, ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context)\
static CK_COHORT_INSTANCE(fas_fas) CK_CC_CACHELINE cohort = CK_COHORT_INITIALIZER
#define LOCK_INIT CK_COHORT_INIT(fas_fas, &cohort, &global_fas_lock, &local_fas_lock)
#define LOCK CK_COHORT_LOCK(fas_fas, &cohort, NULL, NULL)
#define UNLOCK CK_COHORT_UNLOCK(fas_fas, &cohort, NULL, NULL)

@ -44,9 +44,25 @@ static struct affinity a;
static unsigned int locked; static unsigned int locked;
static int nthr; static int nthr;
static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER; static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;
typedef ck_spinlock_fas_t ck_spinlock_fas;
CK_COHORT_PROTOTYPE(fas_fas, ck_spinlock_fas, ck_spinlock_fas) static void
static struct ck_cohort_fas_fas *cohorts; ck_spinlock_fas_lock_with_context(ck_spinlock_fas_t *lock, void *context)
{
(void)context;
ck_spinlock_fas_lock(lock);
}
static void
ck_spinlock_fas_unlock_with_context(ck_spinlock_fas_t *lock, void *context)
{
(void)context;
ck_spinlock_fas_unlock(lock);
}
CK_COHORT_PROTOTYPE(fas_fas,
ck_spinlock_fas_t, ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context,
ck_spinlock_fas_t, ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context)
static CK_COHORT_INSTANCE(fas_fas) *cohorts;
static int n_cohorts; static int n_cohorts;
static void * static void *
@ -55,7 +71,7 @@ thread(void *null CK_CC_UNUSED)
int i = ITERATE; int i = ITERATE;
unsigned int l; unsigned int l;
unsigned int core; unsigned int core;
struct ck_cohort_fas_fas *cohort; CK_COHORT_INSTANCE(fas_fas) *cohort;
if (aff_iterate_core(&a, &core)) { if (aff_iterate_core(&a, &core)) {
perror("ERROR: Could not affine thread"); perror("ERROR: Could not affine thread");
@ -65,7 +81,7 @@ thread(void *null CK_CC_UNUSED)
cohort = cohorts + (core / (int)(a.delta)) % n_cohorts; cohort = cohorts + (core / (int)(a.delta)) % n_cohorts;
while (i--) { while (i--) {
ck_cohort_fas_fas_lock(cohort); CK_COHORT_LOCK(fas_fas, cohort, NULL, NULL);
{ {
l = ck_pr_load_uint(&locked); l = ck_pr_load_uint(&locked);
if (l != 0) { if (l != 0) {
@ -100,7 +116,7 @@ thread(void *null CK_CC_UNUSED)
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l); ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
} }
} }
ck_cohort_fas_fas_unlock(cohort); CK_COHORT_UNLOCK(fas_fas, cohort, NULL, NULL);
} }
return (NULL); return (NULL);
@ -138,10 +154,10 @@ main(int argc, char *argv[])
a.delta = atoi(argv[3]); a.delta = atoi(argv[3]);
fprintf(stderr, "Creating cohorts..."); fprintf(stderr, "Creating cohorts...");
cohorts = malloc(sizeof(struct ck_cohort_fas_fas) * n_cohorts); cohorts = malloc(sizeof(CK_COHORT_INSTANCE(fas_fas)) * n_cohorts);
for (i = 0 ; i < n_cohorts ; i++) { for (i = 0 ; i < n_cohorts ; i++) {
local_lock = malloc(sizeof(ck_spinlock_fas_t)); local_lock = malloc(sizeof(ck_spinlock_fas_t));
ck_cohort_fas_fas_init(cohorts + i, &global_fas_lock, local_lock); CK_COHORT_INIT(fas_fas, cohorts + i, &global_fas_lock, local_lock);
} }
fprintf(stderr, "done\n"); fprintf(stderr, "done\n");

Loading…
Cancel
Save