[LinuxPPS] Locking code

Rodolfo Giometti giometti at enneenne.com
Mon Nov 27 00:18:39 CET 2006


On Sun, Nov 26, 2006 at 10:57:11PM +0100, Rodolfo Giometti wrote:
> 
> I just published new code with locking code. After that we should be
> ready to submit LinuxPPS to linux kernel main tree.

Ok guys, I should stop doing late-night-hacking since last patch was
__broken__! Sorry...

I just fixed bot git repository and the ntp-pps-2.6.19-rc2.diff patch
on my site, also attached you can find the new locking patch.

Ciao,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti at enneenne.com
Linux Device Driver                             giometti at gnudd.com
Embedded Systems                     		giometti at linux.it
UNIX programming                     phone:     +39 349 2432127
-------------- next part --------------
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 1593dd3..ca5fa4d 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -48,12 +48,12 @@ static void linuxpps_add_offeset(struct 
 
 /* --- Exported functions -------------------------------------------------- */
 
-int linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id)
+static inline int __linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id)
 {
 	int i, ret;
 
 	if (try_id >= 0) {
-		if (linuxpps_is_allocated(try_id)) {
+		if (__linuxpps_is_allocated(try_id)) {
 			err("source id %d busy", try_id);
 			return -EBUSY;
 		}
@@ -61,7 +61,7 @@ int linuxpps_register_source(struct linu
 	}
 	else {
 		for (i = 0; i < LINUXPPS_MAX_SOURCES; i++)
-			if (!linuxpps_is_allocated(i))
+			if (!__linuxpps_is_allocated(i))
 				break;
 		if (i >= LINUXPPS_MAX_SOURCES) {
 			err("no free source ids");
@@ -97,12 +97,24 @@ int linuxpps_register_source(struct linu
 	return i;
 }
 
-void linuxpps_unregister_source(struct linuxpps_source_info_s *info)
+int linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&linuxpps_lock, flags);
+	ret = __linuxpps_register_source(info, default_params, try_id);
+	spin_unlock_irqrestore(&linuxpps_lock, flags);
+
+	return ret;
+}
+
+static inline void __linuxpps_unregister_source(struct linuxpps_source_info_s *info)
 {  
 	int i;
 
 	for (i = 0; i < LINUXPPS_MAX_SOURCES; i++)
-		if (linuxpps_is_allocated(i) && linuxpps_source[i].info == info)
+		if (__linuxpps_is_allocated(i) && linuxpps_source[i].info == info)
 			break;
 
 	if (i >= LINUXPPS_MAX_SOURCES) {
@@ -115,10 +127,23 @@ void linuxpps_unregister_source(struct l
 	linuxpps_source[i].info = NULL; 
 } 
 
+void linuxpps_unregister_source(struct linuxpps_source_info_s *info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&linuxpps_lock, flags);
+	__linuxpps_unregister_source(info);
+	spin_unlock_irqrestore(&linuxpps_lock, flags);
+}
+
 void linuxpps_event(int source, int event)
 {
 	struct timespec ts;
 
+	/* In this function we shouldn't need locking at all since each PPS
+	 * source arrives once per second and due the per-PPS source data
+	 * array... */
+
 	/* First of all we get the time stamp... */
 	do_gettimeofday((struct timeval *) &ts);
 	ts.tv_nsec *= 1000;	  /* microseconds to nanoseconds */
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 867fb39..f5ba18b 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -32,6 +32,7 @@ #include <linux/pps.h>
 /* --- Global variables ---------------------------------------------------- */
 
 struct linuxpps_s linuxpps_source[LINUXPPS_MAX_SOURCES];
+spinlock_t linuxpps_lock = SPIN_LOCK_UNLOCKED;
 
 /* --- Local variables ----------------------------------------------------- */
 
diff --git a/include/linux/pps.h b/include/linux/pps.h
index 8965c29..5302e39 100644
--- a/include/linux/pps.h
+++ b/include/linux/pps.h
@@ -72,13 +72,25 @@ struct linuxpps_s {
 /* --- Global variables ---------------------------------------------------- */
 
 extern struct linuxpps_s linuxpps_source[LINUXPPS_MAX_SOURCES];
+extern spinlock_t linuxpps_lock;
 
 /* --- Global functions ---------------------------------------------------- */
 
-static inline int linuxpps_is_allocated(int source) {
+static inline int __linuxpps_is_allocated(int source) {
 	return linuxpps_source[source].info != NULL;
 }
 
+static inline int linuxpps_is_allocated(int source) {
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&linuxpps_lock, flags);
+	ret = __linuxpps_is_allocated(source);
+	spin_unlock_irqrestore(&linuxpps_lock, flags);
+
+	return ret;
+}
+
 /* --- Exported functions -------------------------------------------------- */
 
 extern int linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id);


More information about the LinuxPPS mailing list