/*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#define kIORegPlaneChildSuffix "ChildLinks"
#define kIORegPlaneNameSuffix "Name"
#define kIORegPlaneLocationSuffix "Location"
+
#define kIORegPlaneParentSuffixLen (sizeof(kIORegPlaneParentSuffix) - 1)
+#define kIORegPlaneChildSuffixLen (sizeof(kIORegPlaneChildSuffix) - 1)
+#define kIORegPlaneNameSuffixLen (sizeof(kIORegPlaneNameSuffix) - 1)
+#define kIORegPlaneLocationSuffixLen (sizeof(kIORegPlaneLocationSuffix) - 1)
static IORegistryEntry * gRegistryRoot;
static OSDictionary * gIORegistryPlanes;
static IORecursiveLock * gPropertiesLock;
static SInt32 gIORegistryGenerationCount;
-#define UNLOCK s_lock_done( &gIORegistryLock )
-#define RLOCK s_lock_read( &gIORegistryLock )
-#define WLOCK s_lock_write( &gIORegistryLock ); \
+#define UNLOCK lck_rw_done( &gIORegistryLock )
+#define RLOCK lck_rw_lock_shared( &gIORegistryLock )
+#define WLOCK lck_rw_lock_exclusive( &gIORegistryLock ); \
gIORegistryGenerationCount++
// make atomic
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-struct s_lock_t {
- lck_spin_t interlock; /* "hardware" interlock field */
- volatile unsigned int
- read_count:16, /* No. of accepted readers */
- want_upgrade:1, /* Read-to-write upgrade waiting */
- want_write:1, /* Writer is waiting, or
- locked for write */
- waiting:1, /* Someone is sleeping on lock */
- can_sleep:1; /* Can attempts to lock go to sleep? */
-};
-
-static struct s_lock_t gIORegistryLock;
-
-/* Time we loop without holding the interlock.
- * The former is for when we cannot sleep, the latter
- * for when our thread can go to sleep (loop less)
- * we shouldn't retake the interlock at all frequently
- * if we cannot go to sleep, since it interferes with
- * any other processors. In particular, 100 is too small
- * a number for powerpc MP systems because of cache
- * coherency issues and differing lock fetch times between
- * the processors
- */
-static unsigned int lock_wait_time[2] = { (unsigned int)-1, 100 } ;
-
-static void
-s_lock_init(
- s_lock_t *l,
- boolean_t can_sleep)
-{
- (void) memset((void *) l, 0, sizeof(s_lock_t));
-
- lck_spin_init(&l->interlock, IOLockGroup, LCK_ATTR_NULL);
- l->want_write = FALSE;
- l->want_upgrade = FALSE;
- l->read_count = 0;
- l->can_sleep = can_sleep;
-}
-
-static void
-s_lock_write(
- register s_lock_t * l)
-{
- register int i;
-
- lck_spin_lock(&l->interlock);
-
- /*
- * Try to acquire the want_write bit.
- */
- while (l->want_write) {
-
- i = lock_wait_time[l->can_sleep ? 1 : 0];
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 && l->want_write)
- continue;
- lck_spin_lock(&l->interlock);
- }
-
- if (l->can_sleep && l->want_write) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
- l->want_write = TRUE;
-
- /* Wait for readers (and upgrades) to finish */
-
- while ((l->read_count != 0) || l->want_upgrade) {
-
- i = lock_wait_time[l->can_sleep ? 1 : 0];
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 && (l->read_count != 0 ||
- l->want_upgrade))
- continue;
- lck_spin_lock(&l->interlock);
- }
+lck_rw_t gIORegistryLock;
+lck_grp_t *gIORegistryLockGrp;
+lck_grp_attr_t *gIORegistryLockGrpAttr;
+lck_attr_t *gIORegistryLockAttr;
- if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
-
- lck_spin_unlock(&l->interlock);
-}
-
-static void
-s_lock_done(
- register s_lock_t * l)
-{
- boolean_t do_wakeup = FALSE;
-
- lck_spin_lock(&l->interlock);
-
- if (l->read_count != 0) {
- l->read_count -= 1;
- }
- else {
- if (l->want_upgrade) {
- l->want_upgrade = FALSE;
- }
- else {
- l->want_write = FALSE;
- }
- }
-
- /*
- * There is no reason to wakeup a waiting thread
- * if the read-count is non-zero. Consider:
- * we must be dropping a read lock
- * threads are waiting only if one wants a write lock
- * if there are still readers, they can't proceed
- */
- if (l->waiting && (l->read_count == 0)) {
- l->waiting = FALSE;
- do_wakeup = TRUE;
- }
-
- lck_spin_unlock(&l->interlock);
-
- if (do_wakeup)
- thread_wakeup((event_t) l);
-}
-
-static void
-s_lock_read(
- register s_lock_t * l)
-{
- register int i;
-
- lck_spin_lock(&l->interlock);
-
- while ( l->want_upgrade || ((0 == l->read_count) && l->want_write )) {
-
- i = lock_wait_time[l->can_sleep ? 1 : 0];
-
- if (i != 0) {
- lck_spin_unlock(&l->interlock);
- while (--i != 0 &&
- (l->want_upgrade || ((0 == l->read_count) && l->want_write )))
- continue;
- lck_spin_lock(&l->interlock);
- }
-
- if (l->can_sleep &&
- (l->want_upgrade || ((0 == l->read_count) && l->want_write ))) {
- l->waiting = TRUE;
- lck_spin_sleep( &l->interlock, LCK_SLEEP_DEFAULT,
- (event_t) l, THREAD_UNINT);
- /* interlock relocked */
- }
- }
-
- l->read_count += 1;
- lck_spin_unlock(&l->interlock);
-
-}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if( !gRegistryRoot) {
- s_lock_init( &gIORegistryLock, true );
+
+ gIORegistryLockGrpAttr = lck_grp_attr_alloc_init();
+ //lck_grp_attr_setstat(gIORegistryLockGrpAttr);
+ gIORegistryLockGrp = lck_grp_alloc_init("IORegistryLock", gIORegistryLockGrpAttr);
+ gIORegistryLockAttr = lck_attr_alloc_init();
+ lck_attr_rw_shared_priority(gIORegistryLockAttr);
+ //lck_attr_setdebug(gIORegistryLockAttr);
+ lck_rw_init( &gIORegistryLock, gIORegistryLockGrp, gIORegistryLockAttr);
+
gRegistryRoot = new IORegistryEntry;
gPropertiesLock = IORecursiveLockAlloc();
gIORegistryPlanes = OSDictionary::withCapacity( 1 );
char key[ kIOMaxPlaneName + 16 ];
char * end;
- strncpy( key, name, kIOMaxPlaneName );
- key[ kIOMaxPlaneName ] = 0;
- end = key + strlen( name );
+ strlcpy( key, name, kIOMaxPlaneName + 1 );
+ end = key + strlen( key );
nameKey = OSSymbol::withCString( key);
- strcpy( end, kIORegPlaneParentSuffix );
+ strlcpy( end, kIORegPlaneParentSuffix, kIORegPlaneParentSuffixLen + 1 );
parentKey = OSSymbol::withCString( key);
- strcpy( end, kIORegPlaneChildSuffix );
+ strlcpy( end, kIORegPlaneChildSuffix, kIORegPlaneChildSuffixLen + 1 );
childKey = OSSymbol::withCString( key);
- strcpy( end, kIORegPlaneNameSuffix );
+ strlcpy( end, kIORegPlaneNameSuffix, kIORegPlaneNameSuffixLen + 1 );
pathNameKey = OSSymbol::withCString( key);
- strcpy( end, kIORegPlaneLocationSuffix );
+ strlcpy( end, kIORegPlaneLocationSuffix, kIORegPlaneLocationSuffixLen + 1 );
pathLocationKey = OSSymbol::withCString( key);
plane = new IORegistryPlane;
#if DEBUG_FREE
#define msg ": attached at free()"
- char buf[ strlen(msg) + 40 ];
+ int len = strlen(msg) + 40;
+ char buf[len];
if( registryTable() && gIOServicePlane) {
if( getParentSetReference( gIOServicePlane )
|| getChildSetReference( gIOServicePlane )) {
- strncpy( buf, getName(), 32);
- buf[32] = 0;
- strcat( buf, msg );
+ strlcpy( buf, getName(), 32);
+ strlcat( buf, msg, len );
IOPanic( buf );
}
}
IORegistryEntry * parent;
const OSSymbol * alias;
int index;
- int len, maxLength, compLen;
+ int len, maxLength, compLen, aliasLen;
char * nextComp;
bool ok;
len = plane->nameKey->getLength();
if( len >= maxLength)
return( false);
- strcpy( nextComp, plane->nameKey->getCStringNoCopy());
+ strlcpy( nextComp, plane->nameKey->getCStringNoCopy(), len + 1);
nextComp[ len++ ] = ':';
nextComp += len;
if( (alias = hasAlias( plane ))) {
- len += alias->getLength();
+ aliasLen = alias->getLength();
+ len += aliasLen;
ok = (maxLength > len);
*length = len;
if( ok)
- strcpy( nextComp, alias->getCStringNoCopy());
+ strlcpy( nextComp, alias->getCStringNoCopy(), aliasLen + 1);
return( ok );
}
nextComp = path + len;
compLen = alias->getLength();
- ok = (maxLength > len + compLen);
+ ok = (maxLength > (len + compLen));
if( ok)
- strcpy( nextComp, alias->getCStringNoCopy());
+ strlcpy( nextComp, alias->getCStringNoCopy(), compLen + 1);
} else {
compLen = maxLength - len;
ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
else
locLen = 0;
- ok = ((len + locLen) < maxLength);
+ ok = ((len + locLen + 1) < maxLength);
if( ok) {
- strcpy( path, compName );
+ strlcpy( path, compName, len + 1 );
if( loc) {
path += len;
len += locLen;
*path++ = '@';
- strcpy( path, loc );
+ strlcpy( path, loc, locLen );
}
*length = len;
}
{}
end--;
if( (end - path) < kIOMaxPlaneName) {
- strncpy( temp, path, end - path );
- temp[ end - path ] = 0;
+ strlcpy( temp, path, end - path + 1 );
RLOCK;
entry = IORegistryEntry::fromPath( "/aliases", plane );
// get plane name
end = strchr( path, ':' );
if( end && ((end - path) < kIOMaxPlaneName)) {
- strncpy( temp, path, end - path );
- temp[ end - path ] = 0;
+ strlcpy( temp, path, end - path + 1 );
plane = getPlane( temp );
path = end + 1;
}
if( opath && length) {
// copy out residual path
- len2 = len + strlen( path );
- if( len2 < *length)
- strcpy( opath + len, path );
- *length = len2;
+ len2 = strlen( path );
+ if( (len + len2) < *length)
+ strlcpy( opath + len, path, len2 + 1 );
+ *length = (len + len2);
} else if( path[0])
// no residual path => must be no tail for success
const OSSymbol *key;
while( (key = (OSSymbol *) iter->getNextObject()) ) {
- const char *keysuffix;
+ size_t keysuffix;
// Get a pointer to this keys suffix
- keysuffix = key->getCStringNoCopy()
- + key->getLength() - kIORegPlaneParentSuffixLen;
- if( !strcmp(keysuffix, kIORegPlaneParentSuffix) ) {
+ keysuffix = key->getLength();
+ if (keysuffix <= kIORegPlaneParentSuffixLen)
+ continue;
+ keysuffix -= kIORegPlaneParentSuffixLen;
+ if( !strncmp(key->getCStringNoCopy() + keysuffix,
+ kIORegPlaneParentSuffix,
+ kIORegPlaneParentSuffixLen + 1) ) {
ret = true;
break;
}
IORegCursor * prev;
prev = where;
- where = (IORegCursor *) IOMalloc( sizeof( IORegCursor));
+ where = (IORegCursor *) IOMalloc( sizeof(IORegCursor));
assert( where);
if( where) {
if( where != &start) {
gone = where;
where = gone->next;
- IOFree( gone, sizeof( IORegCursor));
+ IOFree( gone, sizeof(IORegCursor));
return( true);
} else