svn commit: r215170 - in user/davidxu/libthr/sys: kern sys

David Xu davidxu at FreeBSD.org
Fri Nov 12 09:34:22 UTC 2010


Author: davidxu
Date: Fri Nov 12 09:34:21 2010
New Revision: 215170
URL: http://svn.freebsd.org/changeset/base/215170

Log:
  Limit total number of robust mutexes a process can hold.

Modified:
  user/davidxu/libthr/sys/kern/kern_umtx.c
  user/davidxu/libthr/sys/sys/proc.h

Modified: user/davidxu/libthr/sys/kern/kern_umtx.c
==============================================================================
--- user/davidxu/libthr/sys/kern/kern_umtx.c	Fri Nov 12 09:12:04 2010	(r215169)
+++ user/davidxu/libthr/sys/kern/kern_umtx.c	Fri Nov 12 09:34:21 2010	(r215170)
@@ -258,6 +258,7 @@ static int			umtx_cvsig_migrate = 1;
 #endif
 
 static struct robust_chain	robust_chains[ROBUST_CHAINS];
+static int	set_max_robust(SYSCTL_HANDLER_ARGS);
 
 SYSCTL_NODE(_debug, OID_AUTO, umtx, CTLFLAG_RW, 0, "umtx debug");
 SYSCTL_INT(_debug_umtx, OID_AUTO, umtx_pi_allocated, CTLFLAG_RD,
@@ -266,6 +267,15 @@ SYSCTL_INT(_debug_umtx, OID_AUTO, umtx_p
 SYSCTL_INT(_debug_umtx, OID_AUTO, umtx_cvsig_migrate, CTLFLAG_RW,
     &umtx_cvsig_migrate, 0, "cvsig migrate");
 
+SYSCTL_PROC(_debug_umtx, OID_AUTO, max_robust_per_proc,
+	CTLTYPE_INT | CTLFLAG_RW, 0, sizeof(int), set_max_robust, "I",
+	"Set maximum number of robust mutex");
+
+static int		max_robust_per_proc = 1500;
+static struct mtx	max_robust_lock;
+static struct timeval	max_robust_lasttime;
+static struct timeval	max_robust_interval;
+
 #define UMTX_STATE
 #ifdef UMTX_STATE
 static int			umtx_cv_broadcast_migrate;
@@ -314,7 +324,7 @@ static void umtx_thread_cleanup(struct t
 static void umtx_exec_hook(void *arg __unused, struct proc *p __unused,
 	struct image_params *imgp __unused);
 static void umtx_exit_hook(void *arg __unused, struct proc *p __unused);
-static struct robust_info *robust_alloc(void);
+static int robust_alloc(struct robust_info **);
 static void robust_free(struct robust_info *);
 static int robust_insert(struct thread *, struct robust_info *);
 static void robust_remove(struct thread *, struct umutex *);
@@ -357,10 +367,14 @@ umtxq_sysinit(void *arg __unused)
 	}
 
 	mtx_init(&umtx_lock, "umtx lock", NULL, MTX_SPIN);
+	mtx_init(&max_robust_lock, "max robust lock", NULL, MTX_DEF);
 	EVENTHANDLER_REGISTER(process_exec, umtx_exec_hook, NULL,
 	    EVENTHANDLER_PRI_ANY);
 	EVENTHANDLER_REGISTER(process_exit, umtx_exit_hook, NULL,
 	    EVENTHANDLER_PRI_ANY);
+
+	max_robust_interval.tv_sec = 10;
+	max_robust_interval.tv_usec = 0;
 }
 
 struct umtx_q *
@@ -2374,7 +2388,7 @@ do_unlock_pp(struct thread *td, struct u
 	umtxq_unlock(&key);
 
 	owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
-	newval = calc_lockword(owner, flags, count, td_exit, &nwake)
+	newval = calc_lockword(owner, flags, count, td_exit, &nwake);
 
 	if (flags & UMUTEX_PRIO_PROTECT) {
 		/*
@@ -2569,7 +2583,16 @@ do_lock_umutex(struct thread *td, struct
 		return (EFAULT);
 
 	if ((flags & UMUTEX_ROBUST) != 0 && mode != _UMUTEX_WAIT) {
-		rob = robust_alloc();
+		error = robust_alloc(&rob);
+		if (error != 0) {
+			if (timeout == NULL) {
+				if (error == EINTR && mode != _UMUTEX_WAIT)
+					error = ERESTART;
+			} else if (error == ERESTART) {
+				error = EINTR;
+			}
+			return (error);
+		}
 		rob->ownertd = td;
 		rob->umtxp = m;
 	}
@@ -4208,19 +4231,42 @@ freebsd32_umtx_op(struct thread *td, str
 }
 #endif
 
-struct robust_info *
-robust_alloc(void)
+int
+robust_alloc(struct robust_info **robpp)
 {
-	struct robust_info *rb;
+	struct proc *p = curproc;
+	int error;
 
-	rb = uma_zalloc(robust_zone, M_ZERO|M_WAITOK);
-	return (rb);
+	atomic_fetchadd_int(&p->p_robustcount, 1);
+	if (p->p_robustcount > max_robust_per_proc) {
+		mtx_lock(&max_robust_lock);
+		while (p->p_robustcount >= max_robust_per_proc) {
+			if (ratecheck(&max_robust_lasttime,
+				 &max_robust_interval)) {
+				printf("Process %lu (%s) exceeded maximum"
+				  "number of robust mutexes\n",
+				   (u_long)p->p_pid, p->p_comm);
+			}
+			error = msleep(&max_robust_per_proc,
+				&max_robust_lock, 0, "maxrob", 0);
+			if (error != 0) {
+				mtx_unlock(&max_robust_lock);
+				return (error);
+			}
+		}
+		mtx_unlock(&max_robust_lock);
+	}
+	*robpp = uma_zalloc(robust_zone, M_ZERO|M_WAITOK);
+	return (0);
 }
 
 static void
-robust_free(struct robust_info *rb)
+robust_free(struct robust_info *robp)
 {
-	uma_zfree(robust_zone, rb);
+	struct proc *p = curproc;
+
+	atomic_fetchadd_int(&p->p_robustcount, -1);
+	uma_zfree(robust_zone, robp);
 }
 
 static unsigned int
@@ -4366,3 +4412,23 @@ umtx_thread_cleanup(struct thread *td)
 	thread_unlock(td);
 	mtx_unlock_spin(&umtx_lock);
 }
+
+static int
+set_max_robust(SYSCTL_HANDLER_ARGS)
+{
+	int error, v;
+
+	v = max_robust_per_proc;
+	error = sysctl_handle_int(oidp, &v, 0, req);
+	if (error)
+		return (error);
+	if (req->newptr == NULL)
+		return (error);
+	if (v <= 0)
+		return (EINVAL);
+	mtx_lock(&max_robust_lock);
+	max_robust_per_proc = v;
+	wakeup(&max_robust_per_proc);
+	mtx_unlock(&max_robust_lock);
+	return (0);
+}

Modified: user/davidxu/libthr/sys/sys/proc.h
==============================================================================
--- user/davidxu/libthr/sys/sys/proc.h	Fri Nov 12 09:12:04 2010	(r215169)
+++ user/davidxu/libthr/sys/sys/proc.h	Fri Nov 12 09:34:21 2010	(r215170)
@@ -524,6 +524,7 @@ struct proc {
 	int		p_boundary_count;/* (c) Num threads at user boundary */
 	int		p_pendingcnt;	/* how many signals are pending */
 	struct itimers	*p_itimers;	/* (c) POSIX interval timers. */
+	int		p_robustcount;	/* (*) Total number of robust mutex. */
 /* End area that is zeroed on creation. */
 #define	p_endzero	p_magic
 


More information about the svn-src-user mailing list