From d4f439f27e5532fc7f5d8c6754bd35e540d5eb2f Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 7 Mar 2012 15:10:49 -0600 Subject: [PATCH] Add rmlock - almost links --- Makefile | 1 + rtems/freebsd/rtems/rtems-bsd-prot.c | 98 ++++++++++++++++++++++++++ rtems/freebsd/rtems/rtems-bsd-rmlock.c | 92 ++++++++++++++++++++++++ testsuite/link01/test.c | 5 ++ 4 files changed, 196 insertions(+) create mode 100644 rtems/freebsd/rtems/rtems-bsd-rmlock.c diff --git a/Makefile b/Makefile index 2792ec0e..0eda60dc 100644 --- a/Makefile +++ b/Makefile @@ -265,6 +265,7 @@ C_FILES = \ rtems/freebsd/rtems/rtems-bsd-condvar.c \ rtems/freebsd/rtems/rtems-bsd-lock.c \ rtems/freebsd/rtems/rtems-bsd-sx.c \ + rtems/freebsd/rtems/rtems-bsd-rmlock.c \ rtems/freebsd/rtems/rtems-bsd-rwlock.c \ rtems/freebsd/rtems/rtems-bsd-generic.c \ rtems/freebsd/rtems/rtems-bsd-panic.c \ diff --git a/rtems/freebsd/rtems/rtems-bsd-prot.c b/rtems/freebsd/rtems/rtems-bsd-prot.c index 3199c4ba..a2631b71 100644 --- a/rtems/freebsd/rtems/rtems-bsd-prot.c +++ b/rtems/freebsd/rtems/rtems-bsd-prot.c @@ -24,11 +24,19 @@ #include #include +#include #include #include +#include static MALLOC_DEFINE(M_CRED, "cred", "credentials"); +static void crextend(struct ucred *cr, int n); +static void crsetgroups_locked(struct ucred *cr, int ngrp, + gid_t *groups); + + + /* * Allocate a zeroed cred structure. */ @@ -140,3 +148,93 @@ crdup(struct ucred *cr) crcopy(newcr, cr); return (newcr); } + +/* + * Extend the passed in credential to hold n items. + */ +static void +crextend(struct ucred *cr, int n) +{ + int cnt; + + /* Truncate? */ + if (n <= cr->cr_agroups) + return; + + /* + * We extend by 2 each time since we're using a power of two + * allocator until we need enough groups to fill a page. + * Once we're allocating multiple pages, only allocate as many + * as we actually need. The case of processes needing a + * non-power of two number of pages seems more likely than + * a real world process that adds thousands of groups one at a + * time. + */ + if ( n < PAGE_SIZE / sizeof(gid_t) ) { + if (cr->cr_agroups == 0) + cnt = MINALLOCSIZE / sizeof(gid_t); + else + cnt = cr->cr_agroups * 2; + + while (cnt < n) + cnt *= 2; + } else + cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); + + /* Free the old array. */ + if (cr->cr_groups) + free(cr->cr_groups, M_CRED); + + cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); + cr->cr_agroups = cnt; +} + +/* + * Copy groups in to a credential, preserving any necessary invariants. + * Currently this includes the sorting of all supplemental gids. + * crextend() must have been called before hand to ensure sufficient + * space is available. + */ +static void +crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) +{ + int i; + int j; + gid_t g; + + KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); + + bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); + cr->cr_ngroups = ngrp; + + /* + * Sort all groups except cr_groups[0] to allow groupmember to + * perform a binary search. + * + * XXX: If large numbers of groups become common this should + * be replaced with shell sort like linux uses or possibly + * heap sort. + */ + for (i = 2; i < ngrp; i++) { + g = cr->cr_groups[i]; + for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--) + cr->cr_groups[j + 1] = cr->cr_groups[j]; + cr->cr_groups[j + 1] = g; + } +} + +/* + * Copy groups in to a credential after expanding it if required. + * Truncate the list to (ngroups_max + 1) if it is too large. + */ +void +crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) +{ + + if (ngrp > ngroups_max + 1) + ngrp = ngroups_max + 1; + + crextend(cr, ngrp); + crsetgroups_locked(cr, ngrp, groups); +} + diff --git a/rtems/freebsd/rtems/rtems-bsd-rmlock.c b/rtems/freebsd/rtems/rtems-bsd-rmlock.c new file mode 100644 index 00000000..dceb2bd6 --- /dev/null +++ b/rtems/freebsd/rtems/rtems-bsd-rmlock.c @@ -0,0 +1,92 @@ +/** + * @file + * + * @ingroup rtems_bsd_rtems + * + * @brief TODO. + */ + +/* + * COPYRIGHT (c) 2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define RMPF_ONQUEUE 1 +#define RMPF_SIGNAL 2 + +/* + * To support usage of rmlock in CVs and msleep yet another list for the + * priority tracker would be needed. Using this lock for cv and msleep also + * does not seem very useful + */ + +static __inline void compiler_memory_barrier(void) { + __asm __volatile("":::"memory"); +} + +static void assert_rm(struct lock_object *lock, int what); +static void lock_rm(struct lock_object *lock, int how); +#ifdef KDTRACE_HOOKS +static int owner_rm(struct lock_object *lock, struct thread **owner); +#endif +static int unlock_rm(struct lock_object *lock); + +struct lock_class lock_class_rm = { + .lc_name = "rm", + .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE, + .lc_assert = assert_rm, +#if 0 +#ifdef DDB + .lc_ddb_show = db_show_rwlock, +#endif +#endif + .lc_lock = lock_rm, + .lc_unlock = unlock_rm, +#ifdef KDTRACE_HOOKS + .lc_owner = owner_rm, +#endif +}; + +static void +assert_rm(struct lock_object *lock, int what) +{ + + panic("assert_rm called"); +} + +static void +lock_rm(struct lock_object *lock, int how) +{ + + panic("lock_rm called"); +} + +static int +unlock_rm(struct lock_object *lock) +{ + + panic("unlock_rm called"); +} + +#ifdef KDTRACE_HOOKS +static int +owner_rm(struct lock_object *lock, struct thread **owner) +{ + + panic("owner_rm called"); +} +#endif diff --git a/testsuite/link01/test.c b/testsuite/link01/test.c index 69293605..7d64baa5 100644 --- a/testsuite/link01/test.c +++ b/testsuite/link01/test.c @@ -9,12 +9,17 @@ #include #include +/* needed by rtems-bsd-resource.c */ int maxproc; + +/* needed by rtems-bsd-prot.c */ int ngroups_max; +/* needed by rtems-bsd-prot.c */ void prison_hold() {} void prison_free() {} +/* needed by rtems-bsd-init-with-irq.c */ void rtems_interrupt_server_initialize(void) { } rtems_task Init(