Mon Mar  7 12:33:20 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  tagged 0.15
Mon Mar  7 12:32:57 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Version 0.15
Mon Mar  7 12:32:24 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Small update to reflect most recent performance numbers.
Mon Mar  7 12:32:00 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Remove unused utilities.
Mon Mar  7 11:56:55 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Whitespace cleanup.
Mon Mar  7 11:49:41 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Initialize mutex with normal type.
  If you don't specify a mutex type, there's no warantee that it will deadlock
  (and we need it to deadlock =). This patch sets the mutex type explicitly to
  normal.
Mon Mar  7 11:40:18 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Fix a possible race when processing a command.
  There's a possible race between a thread marks itself idle by setting
  thread_idle[tid] = 0 and when it marks its assigned fd idle with fd_busy[fd] =
  0. The fix is just swap the way the assignments are done.
Mon Mar  7 11:37:02 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Fix tid assignment.
  This fixes a really stupid bug that NPTL and a 2.6 kernel put to light
  (probably due to luck and schedule changes =) in the way tids are assigned.
Mon Mar  7 11:36:01 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * Headers cleanup.
Mon Mar  7 10:31:14 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  * get_cmd() leak fix.
  There's a sutble leak in an error path inside net_get_cmd() where 'cmd' could
  get malloc()'ed but if some error conditions are met (wrong version or huge
  payload) we return without freeing it. This patch fixes it.
Mon Mar  7 10:30:15 ART 2005  Alberto Bertogli <albertogli@telpin.com.ar>
  tagged 0.14
diff -rN -u old-old/hash.c new-old/hash.c
--- old-old/hash.c	2005-03-07 12:49:14.681993735 -0300
+++ new-old/hash.c	2005-03-07 11:54:30.000000000 -0300
@@ -35,7 +35,7 @@
 {
 	unsigned int h;
 	unsigned char *p;
-	
+
 	h = 0;
 	for ( p = (unsigned char *)s; *p != '\0'; p++) {
 		h = HASH_MULTIPLIER * h + *p;
@@ -56,7 +56,7 @@
 	h = hash(objname);
 	pthread_mutex_unlock(&hash_lock[h]);
 }
-		
+
 
 /* from now on is just boring hash manipulation functions */
 /* TODO: support multiple hash tables */
@@ -96,7 +96,7 @@
 	int h;
 	int rv = 0;
 	struct hentry *p = NULL, *prev = NULL;
-	
+
 	h = hash(objname);
 
 	for (p = hash_table[h]; p != NULL; p = p->next) {
diff -rN -u old-old/include/lock.h new-old/include/lock.h
--- old-old/include/lock.h	2005-03-07 12:49:14.688992986 -0300
+++ new-old/include/lock.h	2005-03-07 11:35:08.000000000 -0300
@@ -1,12 +1,6 @@
 #ifndef _LOCK_H
 #define _LOCK_H
 
-#include <pthread.h>
-
-typedef pthread_mutex_t lock_t;
-
-int lock_test();
-
 int lock_acquire(char *s, int fd);
 int lock_trylock(char *s, int fd);
 int lock_release(char *s);
diff -rN -u old-old/list.c new-old/list.c
--- old-old/list.c	2005-03-07 12:49:14.681993735 -0300
+++ new-old/list.c	2005-03-07 11:54:51.000000000 -0300
@@ -8,7 +8,7 @@
 
 struct list *list_add(struct list *head, char *name) {
 	struct list *l;
-	
+
 	l = (struct list *) malloc(sizeof(struct list));
 	l->len = strlen(name) + 1;
 	l->name = (char *) malloc(l->len);
@@ -45,7 +45,7 @@
 
 struct list *list_lookup(struct list *head, char *name) {
 	struct list *p;
-	
+
 	for (p = head; p != NULL; p = p->next)
 		if (strncmp(name, p->name, p->len) == 0)
 			return p;
diff -rN -u old-old/lock.c new-old/lock.c
--- old-old/lock.c	2005-03-07 12:49:14.690992772 -0300
+++ new-old/lock.c	2005-03-07 11:55:00.000000000 -0300
@@ -1,5 +1,4 @@
 
-#include <pthread.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,7 +15,7 @@
 	struct hentry *h;
 
 	h = hash_lookup(s, 1);
-	
+
 	if (h->locked == 1) {
 		h->wq = wq_add(h->wq, fd);
 		rv = 0;
@@ -54,9 +53,9 @@
 int lock_release(char *s) {
 	int rv;
 	struct hentry *h;
-	
+
 	h = hash_lookup(s, 0);
-	
+
 	if (h) {
 		h->locked = 0;
 		rv = h->fd;
@@ -68,7 +67,7 @@
 	} else {
 		rv = 0;
 	}
-	
+
 	return rv;
 }
 
@@ -76,7 +75,7 @@
 int lock_set_fd(char *s, int fd) {
 	int rv;
 	struct hentry *h;
-	
+
 	h = hash_lookup(s, 0);
 
 	if (h) {
diff -rN -u old-old/main.c new-old/main.c
--- old-old/main.c	2005-03-07 12:49:14.689992879 -0300
+++ new-old/main.c	2005-03-07 11:55:26.000000000 -0300
@@ -1,6 +1,6 @@
-/* 
+/*
  * Open Lock Daemon
- * 
+ *
  * Alberto Bertogli (albertogli@telpin.com.ar), 2003
  */
 
@@ -10,6 +10,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <signal.h>
+#include <pthread.h>
 
 #include "config.h"
 #include "lock.h"
@@ -71,23 +72,23 @@
 	if (!net_init(nthreads)) {
 		exit(1);
 	}
-	
+
 	/* create the threads */
 	threads = malloc(nthreads * sizeof(pthread_t));
 	for (i = 0; i < nthreads; i++) {
 		/* we pass the thread number as the parameter pointer, which
 		 * is used to index several arrays inside net.c */
-		pthread_create(threads + i, NULL, &net_proc_loop, (void *) &i);
+		pthread_create(threads + i, NULL, &net_proc_loop, (void *) i);
 	}
 
 	/* main select loop */
 	net_select_loop(nthreads);
-	
+
 	/* wait for threads to complete */
 	for (i = 0; i < nthreads; i++) {
 		pthread_join(*(threads + i), NULL);
 	}
-	
+
 	return 0;
 }
 
diff -rN -u old-old/Make.conf new-old/Make.conf
--- old-old/Make.conf	2005-03-07 12:49:14.683993521 -0300
+++ new-old/Make.conf	2005-03-07 12:26:40.000000000 -0300
@@ -1,8 +1,8 @@
 
-VERSION = "0.14"
+VERSION = "0.15"
 
 CC = gcc
-CFLAGS += -Wall -O6
+CFLAGS += -Wall -O6 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE=1 -D_SVID_SOURCE=1
 LIBS += -lpthread
 INCLUDES += -I$(PWD)/include
 
diff -rN -u old-old/net.c new-old/net.c
--- old-old/net.c	2005-03-07 12:49:14.691992665 -0300
+++ new-old/net.c	2005-03-07 12:25:23.000000000 -0300
@@ -14,6 +14,8 @@
 #include <fcntl.h>
 #include <string.h>
 #include <errno.h>
+#include <pthread.h>
+#include <sched.h>
 
 #include "wqueue.h"
 #include "hash.h"
@@ -66,8 +68,8 @@
 static pthread_mutex_t thread_lock[MAXTHREADS];
 
 
-/* 
- * private functions prototypes (publics are defined in net.h) 
+/*
+ * private functions prototypes (publics are defined in net.h)
  */
 
 static int net_send_cmd(int fd, unsigned int op, char *payload, int len);
@@ -86,27 +88,30 @@
 int net_init(int nthreads) {
 	int i, rv;
 	struct sockaddr_in addr;
+	pthread_mutexattr_t attr;
 
 	/* initialize per-thread info */
+	pthread_mutexattr_init(&attr);
+	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
 	for (i = 0; i < nthreads; i++) {
-		pthread_mutex_init(&thread_lock[i], NULL);
+		pthread_mutex_init(&thread_lock[i], &attr);
 		pthread_mutex_lock(&thread_lock[i]);
 		thread_busy[i] = 0;
 		fd_to_process[i] = 0;
 	}
-		
+
 	/* build the listening socket */
 	addr.sin_family = AF_INET;
 	addr.sin_port = htons(PORT);
 	addr.sin_addr.s_addr = INADDR_ANY;
-	
+
 	lfd = socket(PF_INET, SOCK_STREAM, 0);
 	rv = bind(lfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
 	if (rv != 0) {
 		perror("Error binding");
 		return 0;
 	}
-	
+
 	/* disable nagle algorithm, otherwise as we often handle small amounts
 	 * of data it can make i/o quite slow */
 	rv = 1;
@@ -125,7 +130,7 @@
 	active_fd[lfd] = 1;
 
 	return 1;
-}	
+}
 
 /* main select loop */
 void net_select_loop(int nthreads) {
@@ -134,14 +139,14 @@
 	bool workdone;
 	fd_set readfds;
 	struct timeval tv;
-	
+
 	tv.tv_sec = ORPHAN_TIMEOUT;
 	tv.tv_usec = 0;
 
 	/* renice ourselves to low priority, to avoid stealing time from
 	 * workers when looping looking for an idle thread */
 	nice(20);
-	
+
 	/* build initially the fd sets for select */
 	maxfd = lfd;
 	FD_ZERO(&readfds);
@@ -156,19 +161,19 @@
 			clean_orphans();
 			tv.tv_sec = ORPHAN_TIMEOUT;
 			tv.tv_usec = 0;
-		} 
-		
+		}
+
 		if (unlikely(rv < 0)) {
 			perror("Error in select");
 			goto rebuild;
 		}
-		
+
 		workdone = 0;
 		for (i = lfd + 1; i <= maxfd; i++) {
 			/* skip the ones not in the set or busy */
 			if (!FD_ISSET(i, &readfds) || fd_busy[i])
 				continue;
-			
+
 			/* loop looking for an idle thread; see
 			 * doc/multithread */
 			busycount = 0;
@@ -186,34 +191,34 @@
 				}
 				busycount++;
 			}
-			
+
 			/* if everybody is busy, yield the cpu */
 			if (unlikely(busycount == nthreads)) {
 				sched_yield();
 			}
-			
+
 			/* if we didn't find any idle thread to assign the
 			 * job, just loop and go back to select */
 		}
-		
+
 		/* handle new connections */
 		if (FD_ISSET(lfd, &readfds)) {
 			connfd = accept(lfd, (struct sockaddr *) NULL, 0);
-			
+
 			if (connfd < 0) {
 				perror("Error in accept");
 				goto rebuild;
 			}
-			
+
 			if (fcntl(connfd, F_SETFL, O_NONBLOCK) != 0) {
 				perror("Error in enabling nonblocking I/O");
 				close(connfd);
 				goto rebuild;
 			}
-			
+
 			if (connfd > maxfd)
 				maxfd = connfd;
-			
+
 			active_fd[connfd] = 1;
 			workdone = 1;
 		}
@@ -222,7 +227,7 @@
 		if (unlikely(!workdone)) {
 			sched_yield();
 		}
-		
+
 		/* rebuild the fd sets for select */
 rebuild:
 		FD_ZERO(&readfds);
@@ -232,45 +237,45 @@
 			}
 		}
 	}
-	
+
 	return;
-	
+
 }
 
 /* processing loop, it's started always as a thread; see doc/multithread */
 void *net_proc_loop(void *tno) {
 	int fd, tid;
 	struct net_cmd *cmd = NULL;
-	
-	tid = *((int *) tno);
+
+	tid = (int) tno;
 
 	for (;;) {
 		/* this lock gets unlocked by net_select_loop when we have an
 		 * fd to process */
 		pthread_mutex_lock(&thread_lock[tid]);
-		
+
 		fd = fd_to_process[tid];
-		
+
 		cmd = net_get_cmd(fd);
 		if (cmd == NULL)
 			goto end_loop;
-		
+
 		//printf("GOT CMD %d: %p\n", cmd->op, cmd->payload);
 		net_parse(fd, cmd);
-		
+
 		if (cmd != NULL) {
 			if (cmd->payload != NULL)
 				free(cmd->payload);
 			free(cmd);
 			cmd = NULL;
 		}
-		
-end_loop:
-		/* mark the thread idle */
-		thread_busy[tid] = 0;
 
+end_loop:
 		/* mark the fd idle */
 		fd_busy[fd] = 0;
+
+		/* mark the thread idle */
+		thread_busy[tid] = 0;
 	}
 	return NULL;
 }
@@ -291,26 +296,26 @@
 			ulen = 0;
 	} else
 		ulen = len;
-	
+
 	header[0] = ((ver << 4) & 0xF0) + (op >> 4);
 	header[1] = ((op << 4) & 0xF0) + ((ulen & 0xFF0000) >> 16);
 	header[2] = (ulen & 0x00FF00) >> 8;
 	header[3] = ulen & 0x0000FF;
-							
+
 	//printf(">>> %hhu %hhu %hhu %hhu\n", header[0], header[1], header[2], header[3]);
-	
+
 	if (unlikely(write(fd, header, 4) != 4)) {
 		clean_buffer(fd);
 		net_close(fd);
 		return 0;
 	}
-	
+
 	if (unlikely(write(fd, payload, ulen) != ulen)) {
 		clean_buffer(fd);
 		net_close(fd);
 		return 0;
 	}
-	
+
 	return 1;
 }
 
@@ -320,11 +325,10 @@
 	struct net_cmd *cmd = NULL;
 	struct part_buf *b = &bufs[fd];
 
-	
 	if (b->cmd == NULL) {
 		/* we have no command filled yet, so we start by reading the
 		 * header */
-		
+
 		/* do the reading into the 4-byte buffer */
 		missing = 4 - b->read_so_far;
 		s = read(fd, b->tmp + b->read_so_far, missing);
@@ -335,9 +339,9 @@
 			}
 			return NULL;
 		}
-		
+
 		b->read_so_far += s;
-		
+
 		if (unlikely(b->read_so_far < 4)) {
 			/* still not enough, so just wait */
 			return NULL;
@@ -346,20 +350,21 @@
 		/* ok, we got our header, so build it */
 		cmd = (struct net_cmd *) malloc(sizeof(struct net_cmd));
 		memset(cmd, 0, sizeof(struct net_cmd));
-		
+
 		cmd->ver = b->tmp[0] >> 4;
 		cmd->op = ((b->tmp[0] & 0x0F ) << 4) + ((b->tmp[1] & 0xF0) >> 4);
 		cmd->len = ( ((int) b->tmp[1] & 0x0F) << 16) +
 			((int) b->tmp[2] << 8) + ((int) b->tmp[3]);
-		
+
 		//printf("VER: %d, LEN: %d\n", cmd->ver, cmd->len);
 		//printf("<<< %hhu %hhu %hhu %hhu\n", b->tmp[0], b->tmp[1], b->tmp[2], b->tmp[3]);
 		if (unlikely(cmd->ver != 1 || cmd->len > MAX_PAYLOAD)) {
+			free(cmd);
 			clean_buffer(fd);
 			net_close(fd);
 			return NULL;
 		}
-		
+
 		if (likely(cmd->len)) {
 			cmd->payload = (char *) malloc(cmd->len);
 			memset(cmd->payload, 0, cmd->len);
@@ -368,7 +373,7 @@
 		}
 
 		b->cmd = cmd;
-		
+
 		/* put read_so_far to 0, it now refers to how much of
 		 * the _payload_ we've read */
 		b->read_so_far = 0;
@@ -377,8 +382,8 @@
 		memset(b->tmp, 0, 4);
 
 		/* we don't return here, just keep going on reading
-		 * the payload */			
-		
+		 * the payload */
+
 	}
 
 	/* we have the entire header, now we read the payload (or what's left
@@ -392,9 +397,9 @@
 		b->cmd = NULL;
 		return cmd;
 	}
-	
+
 	missing = b->cmd->len - b->read_so_far;
-	
+
 	s = read(fd, b->cmd->payload + b->read_so_far, missing);
 	if (unlikely(s <= 0)) {
 		if (s == 0 || (errno != EAGAIN && errno != EINTR)) {
@@ -404,7 +409,7 @@
 		return NULL;
 	}
 	b->read_so_far += s;
-	
+
 	if (likely(b->read_so_far == b->cmd->len)) {
 		/* the command is complete! */
 		cmd = b->cmd;
@@ -421,7 +426,7 @@
 /* closes a fd */
 static int net_close(int fd) {
 	struct list *p;
-	
+
 	active_fd[fd] = 0;
 
 	/* move open locks to the orphan list */
@@ -429,12 +434,12 @@
 		/* first, mark its open locks as orphans */
 		for (p = olocks[fd]; p != NULL; p = p->next)
 			lock_set_fd(p->name, -1);
-			
+
 		/* and then move them to the orphan list */
 		orphans = list_mult_add(orphans, olocks[fd]);
 		olocks[fd] = NULL;
 	}
-	
+
 	return close(fd);
 }
 
@@ -444,7 +449,7 @@
 	char *data = cmd->payload;
 	unsigned int op = cmd->op;
 	int hfd, send_op = 0;
-	
+
 	if (unlikely( data != NULL && (*(data + (cmd->len - 1)) != '\0' ) )) {
 		/* the payload doesn't end in '\0' */
 		//printf("BROKEN STRING! ");
@@ -452,7 +457,7 @@
 		net_close(fd);
 		return 1;
 	}
-	
+
 	switch (op) {
 		case REQ_ACQ_LOCK:
 			if (unlikely(cmd->len == 0))
@@ -467,7 +472,7 @@
 			hash_unlock_chain(data);
 			net_send_cmd(fd, send_op, data, cmd->len);
 			break;
-			
+
 		case REQ_REL_LOCK:
 			if (unlikely(cmd->len == 0))
 				goto return_error;
@@ -486,7 +491,7 @@
 			hash_unlock_chain(data);
 			net_send_cmd(fd, send_op, data, cmd->len);
 			break;
-			
+
 		case REQ_TRY_LOCK:
 			if (unlikely(cmd->len == 0))
 				goto return_error;
@@ -537,7 +542,7 @@
 int net_wakeup(struct hentry *h) {
 	int fd;
 	struct wqentry *p;
-	
+
 	/* get the fd from the first of the list */
 	fd = h->wq->fd;
 	active_fd[fd] = 1;
@@ -550,11 +555,11 @@
 
 	/* of course, mark it locked */
 	h->locked = 1;
-	
+
 	/* add the open lock; the caller will take care to remove from the
 	 * other queue */
 	olocks[fd] = list_add(olocks[fd], h->objname);
-		
+
 	/* and send the reply */
 	net_send_cmd(fd, REP_LOCK_ACQUIRED, h->objname, h->len);
 	return 1;
@@ -565,7 +570,7 @@
  * command parser */
 static void clean_orphans() {
 	struct list *p;
-	
+
 	for (p = orphans; p != NULL; p = p->next) {
 		hash_lock_chain(p->name);
 		lock_release(p->name);
@@ -593,6 +598,6 @@
 		b->tmp = NULL;
 	}
 	*/
-}	
+}
 
 
diff -rN -u old-old/README new-old/README
--- old-old/README	2005-03-07 12:49:14.672994699 -0300
+++ new-old/README	2005-03-07 12:28:59.000000000 -0300
@@ -27,9 +27,9 @@
 solid and quite usable. Check the TODO list for more details.
 
 It doesn't perform bad, it makes around 1200 (lock A; unlock A) operations per
-second on a Pentium II 400Mhz, and about 5400 on a Pentium IV 2Ghz. It's also
-quite small, the compiled binary is about 14k and the memory footprint about
-300k (depending on the usage, the number of threads, and the amount of
+second on a Pentium II 400Mhz, and about 7850 on a Pentium IV 2.8Ghz. It's
+also quite small, the compiled binary is about 10k and the memory footprint
+about 300k (depending on the usage, the number of threads, and the amount of
 simultaneous locks held). Paralell tests are coherent with those numbers,
 reproducing them here would be too much.
 
diff -rN -u old-old/utils/psenv new-old/utils/psenv
--- old-old/utils/psenv	2005-03-07 12:49:14.673994592 -0300
+++ new-old/utils/psenv	1969-12-31 21:00:00.000000000 -0300
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# sets the environment to work using Andrew Morton great patch scripts
-
-# run it in the top directory, like:
-#  . utils/psenv
-
-
-# create the directories
-for i in ps/pc ps/patches ps/txt; do
-	if [ ! -d $i ]; then
-		mkdir -p -v $i
-	fi
-done
-
-
-PATH=/root/bin/patch-scripts:$PATH
-PATCHSCRIPTS=./ps
-
-export PATH
-export PATCHSCRIPTS
-
diff -rN -u old-old/utils/vicl new-old/utils/vicl
--- old-old/utils/vicl	2005-03-07 12:49:14.673994592 -0300
+++ new-old/utils/vicl	1969-12-31 21:00:00.000000000 -0300
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# yeah i work as root =)
-DIR=/root/devel/old/cur
-
-cd $DIR
-cd doc
-cp Changelog Changelog~
-
-DATE=`date '+%d %h %y %H.%M.%S'`
-echo "$DATE - Alberto <albertogli@telpin.com.ar>"  > Changelog
-echo " * " >> Changelog
-echo >> Changelog
-
-cat Changelog~ >> Changelog
-
-vi Changelog
-
-rm Changelog~
- 
diff -rN -u old-old/wqueue.c new-old/wqueue.c
--- old-old/wqueue.c	2005-03-07 12:49:14.678994057 -0300
+++ new-old/wqueue.c	2005-03-07 11:56:45.000000000 -0300
@@ -13,7 +13,7 @@
 	new = (struct wqentry *) malloc(sizeof(struct wqentry));
 	new->fd = fd;
 	new->next = NULL;
-	
+
 	/* if wq is NULL, it means it's empty, so we just replace it with our
 	 * new one */
 	if (wq == NULL) {
@@ -22,7 +22,7 @@
 		/* go to the last one */
 		for(aux = wq; aux->next != NULL; aux = aux->next)
 			;
-		
+
 		aux->next = new;
 	}
 	return wq;
@@ -32,7 +32,7 @@
 int wq_del(struct wqentry *wq, int fd) {
 	struct wqentry *p, *prev;
 	prev = NULL;
-	
+
 	/* go through the list looking */
 	for(p = wq; p != NULL; p = p->next) {
 		if (p->fd == fd) {


