[Cluster-devel] cluster/dlm/tests/usertest Makefile threads.c

pcaulfield at sourceware.org pcaulfield at sourceware.org
Thu Feb 1 11:11:51 UTC 2007


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	pcaulfield at sourceware.org	2007-02-01 11:11:51

Modified files:
	dlm/tests/usertest: Makefile 
Added files:
	dlm/tests/usertest: threads.c 

Log message:
	Add threads example

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/dlm/tests/usertest/threads.c.diff?cvsroot=cluster&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/dlm/tests/usertest/Makefile.diff?cvsroot=cluster&r1=1.9&r2=1.10

/cvs/cluster/cluster/dlm/tests/usertest/threads.c,v  -->  standard output
revision 1.1
--- cluster/dlm/tests/usertest/threads.c
+++ -	2007-02-01 11:11:51.819404000 +0000
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Threaded DLM example
+ */
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <limits.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include "libdlm.h"
+
+struct lock_wait {
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+	struct dlm_lksb lksb;
+};
+
+struct thread_args
+{
+	dlm_lshandle_t *lockspace;
+	char *resource;
+	int flags;
+	int delay;
+	int mode;
+	int verbose;
+	int num;
+};
+
+static int modetonum(char *modestr)
+{
+    int mode = LKM_EXMODE;
+
+    if (strncasecmp(modestr, "NL", 2) == 0) mode = LKM_NLMODE;
+    if (strncasecmp(modestr, "CR", 2) == 0) mode = LKM_CRMODE;
+    if (strncasecmp(modestr, "CW", 2) == 0) mode = LKM_CWMODE;
+    if (strncasecmp(modestr, "PR", 2) == 0) mode = LKM_PRMODE;
+    if (strncasecmp(modestr, "PW", 2) == 0) mode = LKM_PWMODE;
+    if (strncasecmp(modestr, "EX", 2) == 0) mode = LKM_EXMODE;
+
+    return mode;
+}
+
+static char *numtomode(int mode)
+{
+    switch (mode)
+    {
+    case LKM_NLMODE: return "NL";
+    case LKM_CRMODE: return "CR";
+    case LKM_CWMODE: return "CW";
+    case LKM_PRMODE: return "PR";
+    case LKM_PWMODE: return "PW";
+    case LKM_EXMODE: return "EX";
+    default: return "??";
+    }
+}
+
+static void usage(char *prog, FILE *file)
+{
+    fprintf(file, "Usage:\n");
+    fprintf(file, "%s [mcnpquhV] <lockname>\n", prog);
+    fprintf(file, "\n");
+    fprintf(file, "   -V           show version of %s\n", prog);
+    fprintf(file, "   -h           show this help information\n");
+    fprintf(file, "   -m <mode>    lock mode (default EX)\n");
+    fprintf(file, "   -n           don't block\n");
+    fprintf(file, "   -t <threads> number of threads\n");
+    fprintf(file, "   -d <secs>    delay while holding lock\n");
+    fprintf(file, "   -l <name>    lockspace name\n");
+    fprintf(file, "   -v           verbose (up to 3)\n");
+    fprintf(file, "\n");
+
+}
+
+/* Simply wakes the thread that initiated the lock */
+static void sync_ast_routine(void *arg)
+{
+	struct lock_wait *lwait = arg;
+
+	pthread_mutex_lock(&lwait->mutex);
+	pthread_cond_signal(&lwait->cond);
+	pthread_mutex_unlock(&lwait->mutex);
+}
+
+/* Get/Convert a lock and wait for it to complete (or fail) */
+static int sync_lock(dlm_lshandle_t lockspace,
+		     const char *resource,
+		     int mode,
+		     int flags,
+		     int *lockid)
+{
+	int status;
+	struct lock_wait lwait;
+
+	if (!lockid) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Conversions need the lockid in the LKSB */
+	if (flags & LKF_CONVERT)
+		lwait.lksb.sb_lkid = *lockid;
+
+	pthread_cond_init(&lwait.cond, NULL);
+	pthread_mutex_init(&lwait.mutex, NULL);
+	pthread_mutex_lock(&lwait.mutex);
+
+	status = dlm_ls_lock(lockspace,
+			     mode,
+			     &lwait.lksb,
+			     flags,
+			     resource,
+			     strlen(resource),
+			     0, sync_ast_routine, &lwait, NULL, NULL);
+	if (status)
+		return status;
+
+	/* Wait for it to complete */
+	pthread_cond_wait(&lwait.cond, &lwait.mutex);
+	pthread_mutex_unlock(&lwait.mutex);
+
+	*lockid = lwait.lksb.sb_lkid;
+
+	errno = lwait.lksb.sb_status;
+
+	if (lwait.lksb.sb_status)
+		return -1;
+	else
+		return 0;
+}
+
+/* Unlock - and wait for it to complete */
+static int sync_unlock(dlm_lshandle_t lockspace, int lockid)
+{
+	int status;
+	struct lock_wait lwait;
+
+	pthread_cond_init(&lwait.cond, NULL);
+	pthread_mutex_init(&lwait.mutex, NULL);
+	pthread_mutex_lock(&lwait.mutex);
+
+	status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
+
+	if (status)
+		return status;
+
+	/* Wait for it to complete */
+	pthread_cond_wait(&lwait.cond, &lwait.mutex);
+	pthread_mutex_unlock(&lwait.mutex);
+
+	errno = lwait.lksb.sb_status;
+	if (lwait.lksb.sb_status != EUNLOCK)
+		return -1;
+	else
+		return 0;
+
+}
+
+static void *thread_fn(void *arg)
+{
+	struct thread_args *ta = arg;
+	int lockid;
+	int status;
+
+	if (ta->verbose > 1)
+		fprintf(stderr, "Locking in thread %d\n", pthread_self);
+
+	status = sync_lock(ta->lockspace, ta->resource,
+			   ta->mode, ta->flags, &lockid);
+
+	if (status)
+	{
+		if (ta->verbose)
+			fprintf(stderr, "Lock in thread %x failed: %s\n", pthread_self, strerror(errno));
+		return NULL;
+	}
+
+	sleep(ta->delay);
+
+	if (ta->verbose > 1)
+		fprintf(stderr, "Unlocking in thread %x\n", pthread_self());
+
+	status = sync_unlock(ta->lockspace,lockid);
+	if (status)
+	{
+		if (ta->verbose)
+			fprintf(stderr, "Unlock in thread %x failed: %s\n", pthread_self(), strerror(errno));
+	}
+
+	return NULL;
+}
+
+
+int main(int argc, char *argv[])
+{
+    char *resource = "LOCK-NAME";
+    char *lockspace_name = "threadtest";
+    dlm_lshandle_t *lockspace;
+    int  flags = 0;
+    int  num_threads = 5;
+    int  delay = 1;
+    int  mode;
+    int  verbose;
+    int  i;
+    signed char opt;
+    pthread_t *threads;
+    struct thread_args ta;
+
+    /* Deal with command-line arguments */
+    opterr = 0;
+    optind = 0;
+    while ((opt=getopt(argc,argv,"h?nt:d:l:m:vV")) != EOF)
+    {
+	switch(opt)
+	{
+	case 'h':
+	    usage(argv[0], stdout);
+	    exit(0);
+
+	case '?':
+	    usage(argv[0], stderr);
+	    exit(0);
+
+	case 'n':
+	    flags |= LKF_NOQUEUE;
+	    break;
+
+	case 't':
+            num_threads = atoi(optarg);
+	    break;
+
+	case 'm':
+            mode = modetonum(optarg);
+	    break;
+
+	case 'l':
+	    lockspace_name = strdup(optarg);
+	    break;
+
+	case 'd':
+            delay = atoi(optarg);
+	    break;
+
+	case 'v':
+	    verbose++;
+	    break;
+
+	case 'V':
+	    printf("\nthread example version 0.1\n\n");
+	    exit(1);
+	    break;
+	}
+    }
+
+    if (argv[optind])
+	resource = argv[optind];
+
+    if (verbose)
+	    fprintf(stderr, "Creating lockspace '%s'...", lockspace_name);
+
+    /* You need to be root to create the lockspace ... but not to use it */
+    lockspace = dlm_create_lockspace(lockspace_name, 0666);
+    if (!lockspace) {
+	    perror("Unable to create lockspace");
+	    return 1;
+    }
+    if (verbose)
+	    fprintf(stderr, "done\n");
+
+    dlm_ls_pthread_init(lockspace);
+
+    threads = malloc(sizeof(pthread_t) * num_threads);
+    if (!threads)
+    {
+	    perror("can't malloc threads array");
+	    return 2;
+    }
+
+    if (verbose)
+	    fprintf(stderr, "Starting threads\n");
+
+    ta.lockspace = lockspace;
+    ta.mode = mode;
+    ta.flags = flags;
+    ta.delay = delay;
+    ta.verbose = verbose;
+    ta.resource = resource;
+
+    for (i=0; i<num_threads; i++)
+    {
+	    if (verbose > 2)
+		    fprintf(stderr, "Starting thread %d\n", i);
+
+	    pthread_create(&threads[i], NULL, thread_fn, &ta);
+    }
+
+    if (verbose)
+	    fprintf(stderr, "All threads started\n");
+
+    for (i=0; i<num_threads; i++)
+    {
+	    void *status;
+	    if (verbose > 2)
+		    fprintf(stderr, "Waiting for thread %d\n", i);
+	    pthread_join(threads[i], &status);
+    }
+
+    return 0;
+}
+
--- cluster/dlm/tests/usertest/Makefile	2007/01/31 22:47:00	1.9
+++ cluster/dlm/tests/usertest/Makefile	2007/02/01 11:11:51	1.10
@@ -12,7 +12,7 @@
 top_srcdir = ../../..
 UNINSTALL=${top_srcdir}/scripts/uninstall.pl
 
-BINARIES=dlmtest asttest lstest pingtest lvb dlmtest2 flood alternate-lvb joinleave
+BINARIES=dlmtest asttest lstest pingtest lvb dlmtest2 flood alternate-lvb joinleave threads
 
 all: $(BINARIES)
 
@@ -53,5 +53,8 @@
 lvb: lvb.c	
 	$(CC) $(CFLAGS) -o $@ $< -ldlm -lpthread
 
+threads: threads.c	
+	$(CC) $(CFLAGS) -o $@ $< -ldlm -lpthread
+
 clean:
 	rm -f *.o $(BINARIES) *~ core




More information about the Cluster-devel mailing list