/**
 * Remove a specific entry node from the list.
 *
 * @param deleted_node The node to be removed.
 *
 * @warning This method is not async safe.
 */
template <typename V> void async_list<V>::nasync_remove_node (node *deleted_node) {
    /* Lock the list from other writers. */
    OSSpinLockLock(&_write_lock); {
        /* Find the record. */
        node *item = _head;
        while (item != NULL) {
            if (item == deleted_node)
                break;
            
            item = item->_next;
        }
        
        /* If not found, nothing to do */
        if (item == NULL) {
            OSSpinLockUnlock(&_write_lock);
            return;
        }
        
        /*
         * Atomically make the item unreachable by readers.
         *
         * This serves as a synchronization point -- after the CAS, the item is no longer reachable via the list.
         */
        if (item == _head) {
            if (!OSAtomicCompareAndSwapPtrBarrier(item, item->_next, (void **) &_head)) {
                PLCF_DEBUG("Failed to remove image list head despite holding lock");
            }
        } else {
            /* There MUST be a non-NULL prev pointer, as this is not HEAD. */
            if (!OSAtomicCompareAndSwapPtrBarrier(item, item->_next, (void **) &item->_prev->_next)) {
                PLCF_DEBUG("Failed to remove image list item despite holding lock");
            }
        }
        
        /* Now that the item is unreachable, update the prev/tail pointers. These are never accessed without a lock,
         * and need not be updated atomically. */
        if (item->_next != NULL) {
            /* Item is not the tail (otherwise next would be NULL), so simply update the next item's prev pointer. */
            item->_next->_prev = item->_prev;
        } else {
            /* Item is the tail (next is NULL). Simply update the tail record. */
            _tail = item->_prev;
        }
        
        /* If a reader is active, place the node on the free list. The item is unreachable here when readers
         * aren't active, so if we have a 0 refcount, we can safely delete the item, and be sure that no
         * reader holds a reference to it. */
        if (_refcount > 0) {
            item->_prev = NULL;
            item->_next = _free;
            
            if (_free != NULL)
                _free->_prev = item;
            _free = item;
        } else {
            delete item;
        }
    } OSSpinLockUnlock(&_write_lock);
}
/**
 * Prepend a new entry value to the list
 *
 * @param value The value to be prepended.
 *
 * @warning This method is not async safe.
 */
template <typename V> void async_list<V>::nasync_prepend (V value) {
    /* Lock the list from other writers. */
    OSSpinLockLock(&_write_lock); {
        /* Construct the new entry, or recycle an existing one. */
        node *new_node;
        if (_free != NULL) {
            /* Fetch a node from the free list */
            new_node = _free;
            new_node->reset(value);
            
            /* Update the free list */
            _free = _free->_next;
        } else {
            new_node = new node(value);
        }
        
        /* Issue a memory barrier to ensure a consistent view of the value. */
        OSMemoryBarrier();
        
        /* If this is the first entry, initialize the list. */
        if (_tail == NULL) {
            
            /* Update the list tail. This need not be done atomically, as tail is never accessed by a lockless reader. */
            _tail = new_node;
            
            /* Atomically update the list head; this will be iterated upon by lockless readers. */
            if (!OSAtomicCompareAndSwapPtrBarrier(NULL, new_node, (void **) (&_head))) {
                /* Should never occur */
                PLCF_DEBUG("An async image head was set with tail == NULL despite holding lock.");
            }
        }
        
        /* Otherwise, prepend to the head of the list */
        else {
            new_node->_next = _head;
            new_node->_prev = NULL;
            
            /* Update the prev pointers. This is never accessed without a lock, so no additional synchronization
             * is required here. */
            _head->_prev = new_node;

            /* Issue a memory barrier to ensure a consistent view of the nodes. */
            OSMemoryBarrier();

            /* Atomically slot the new record into place; this may be iterated on by a lockless reader. */
            if (!OSAtomicCompareAndSwapPtrBarrier(new_node->_next, new_node, (void **) (&_head))) {
                PLCF_DEBUG("Failed to prepend to image list despite holding lock");
            }
        }
    } OSSpinLockUnlock(&_write_lock);
}
__private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) {
    static CFStringRef __byHostIdentifierString = NULL;

    if (!__byHostIdentifierString) {
        CFStringRef hostID = _CFGetHostUUIDString();
        if (hostID) {
            if (CFStringHasPrefix(hostID, CFSTR("00000000-0000-1000-8000-"))) {
                // If the host UUID is prefixed by "00000000-0000-1000-8000-" then the UUID returned is the "compatible" type. The last field of the string will be the MAC address of the primary ethernet interface of the computer. We use this for compatibility with existing by-host preferences.
                CFStringRef lastField = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, hostID, CFRangeMake(24, 12));
                CFMutableStringRef tmpstr = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, lastField);
                CFStringLowercase(tmpstr, NULL);
                CFStringRef downcasedField = CFStringCreateCopy(kCFAllocatorSystemDefault, tmpstr);
                
                if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)downcasedField, (void *)&__byHostIdentifierString)) {
                    CFRelease(downcasedField);
                }
                
                CFRelease(tmpstr);
                CFRelease(lastField);
            } else {
                // The host UUID is a full UUID, and we should just use that. This doesn't involve any additional string creation, so we should just be able to do the assignment.
                __byHostIdentifierString = hostID;
            }
        } else {
            __byHostIdentifierString = CFSTR("UnknownHostID");
        }
    }
    
    return __byHostIdentifierString;
}
__private_extern__ CFStringRef _CFGetHostUUIDString(void) {
    static CFStringRef __hostUUIDString = NULL;
    
    if (!__hostUUIDString) {
        CFUUIDBytes uuidBytes;
        int getuuidErr = 0;
        struct timespec timeout = {0, 0};   // Infinite timeout for gethostuuid()
        
        getuuidErr = gethostuuid((unsigned char *)&uuidBytes, &timeout);
        if (getuuidErr == -1) {
            // An error has occurred trying to get the host UUID string. There's nothing we can do here, so we should just return NULL.
            CFLog(kCFLogLevelWarning, CFSTR("_CFGetHostUUIDString: unable to determine UUID for host. Error: %d"), errno);
            return NULL;
        }
        
        CFUUIDRef uuidRef = CFUUIDCreateFromUUIDBytes(kCFAllocatorSystemDefault, uuidBytes);
        CFStringRef uuidAsString = CFUUIDCreateString(kCFAllocatorSystemDefault, uuidRef);
        
        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)uuidAsString, (void *)&__hostUUIDString)) {
            CFRelease(uuidAsString);    // someone else made the assignment, so just release the extra string.
        }
        
        CFRelease(uuidRef);
    }
    
    return __hostUUIDString;
}
Esempio n. 5
0
/*
** Initialize this module.
*/
static int sqlite3MemInit(void *NotUsed){
#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
  int cpuCount;
  size_t len;
  if( _sqliteZone_ ){
    return SQLITE_OK;
  }
  len = sizeof(cpuCount);
  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
  sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
  if( cpuCount>1 ){
    /* defer MT decisions to system malloc */
    _sqliteZone_ = malloc_default_zone();
  }else{
    /* only 1 core, use our own zone to contention over global locks, 
    ** e.g. we have our own dedicated locks */
    bool success;
    malloc_zone_t* newzone = malloc_create_zone(4096, 0);
    malloc_set_zone_name(newzone, "Sqlite_Heap");
    do{
      success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, 
                                 (void * volatile *)&_sqliteZone_);
    }while(!_sqliteZone_);
    if( !success ){
      /* somebody registered a zone first */
      malloc_destroy_zone(newzone);
    }
  }
#endif
  UNUSED_PARAMETER(NotUsed);
  return SQLITE_OK;
}
Esempio n. 6
0
static PyObject * Reference_compare_and_set(Reference * self, PyObject * args) {
	PyObject *expect_value, *new_value;
	if (!PyArg_ParseTuple(args, "OO", &expect_value, &new_value)) {
		return NULL;
	}
	Py_INCREF(self->value);
	Py_INCREF(expect_value);
	Py_INCREF(new_value);
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
	if (OSAtomicCompareAndSwapPtrBarrier(expect_value, new_value,
				(void * volatile)&self->value)) {
		Py_INCREF(Py_True);
		return Py_True;
	}
#elif defined(_MSC_VER)
	if (InterlockedCompareExchange(&self->value, new_value, old_value)) {
		Py_INCREF(Py_True);
		return Py_True;
	}
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
	if (__sync_bool_compare_and_swap(&self->value, expect_value, new_value)) {
		Py_INCREF(Py_True);
		return Py_True;
	}
#else
#error No CAS operation available for this platform
#endif
	Py_INCREF(Py_False);
	return Py_False;
}
Esempio n. 7
0
__private_extern__ CFStringRef _CFProcessNameString(void) {
    static CFStringRef __CFProcessNameString = NULL;
    if (!__CFProcessNameString) {
        const char *processName = *_CFGetProgname();
        if (!processName) processName = "";
        CFStringRef newStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, processName, kCFPlatformInterfaceStringEncoding);
        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *) newStr, (void * volatile *)& __CFProcessNameString)) {
            CFRelease(newStr);    // someone else made the assignment, so just release the extra string.
        }
    }
    return __CFProcessNameString;
}
void dyld_register_tlv_state_change_handler(enum dyld_tlv_states state, dyld_tlv_state_change_handler handler)
{
	TLVHandler *h = malloc(sizeof(TLVHandler));
	h->state = state;
	h->handler = Block_copy(handler);

	TLVHandler *old;
	do {
		old = tlv_handlers;
		h->next = old;
	} while (! OSAtomicCompareAndSwapPtrBarrier(old, h, (void * volatile *)&tlv_handlers));
}
Esempio n. 9
0
File: ia32.cpp Progetto: Marlinc/0ad
bool cpu_CAS(volatile intptr_t* location, intptr_t expected, intptr_t newValue)
{
	cassert(sizeof(intptr_t) == sizeof(void*));
	return OSAtomicCompareAndSwapPtrBarrier((void*)expected, (void*)newValue, (void* volatile*)location);
}
Esempio n. 10
0
void SwapMachMessage( sComData *message, eSwapDirection direction )
{
    short i;
    sObject* object;
    bool isTwoWay = false;
    
    if (message == nil) return;
    
#ifdef DUMP_BUFFER
    UInt32 bufSize = 0;
    if ( gDumpFile == NULL )
	{
		FILE *tempFile = fopen( "/Library/Logs/DirectoryService/MachMsgDump", "w" );
		if ( OSAtomicCompareAndSwapPtrBarrier(NULL, tempFile, (void **) &gDumpFile) == false )
		{
			// close the file.
			fclose( tempFile );
		}
	}
        
    if (direction == kDSSwapNetworkToHostOrder)
        fprintf(gDumpFile, "\n\n\nBuffer in Network order (preSwap)\n");
    else
        fprintf(gDumpFile, "\n\n\nBuffer in Host order (preSwap)\n");
	
    for (i=0; i< 10; i++)
    {
        object = &message->obj[i];
        UInt32 objType = DSGetLong(&object->type, direction);
        UInt32 offset = DSGetLong(&object->offset, direction);
        UInt32 length = DSGetLong(&object->length, direction);
        char* type = "unknown";
        if (objType >= kResult && objType <= kAttrValueList)
            type = objectTypes[objType - kResult];
        if (objType != 0)
        {
            if (length > 0)
                    fprintf(gDumpFile, "Object %d, type %s, offset %ld, size %ld\n", i, type, DSGetLong(&object->offset, direction), DSGetLong(&object->length, direction));
            else
                    fprintf(gDumpFile, "Object %d, type %s, value %ld\n", i, type, DSGetLong(&object->count, direction));
        }
        if (length > 0)
        {
            UInt32 size = offset + length - sizeof(sComData) + 4;
            if (size > bufSize) bufSize = size;
        }
    }
    DumpBuf(message->data, bufSize);
#endif
    
    DSSwapLong(&message->fDataSize, direction);
    DSSwapLong(&message->fDataLength, direction);
    DSSwapLong(&message->fMsgID, direction);
    
	UInt32 aNodeRef = 0;

	//handle CustomCall endian issues - need to determine which plugin is being used
	bool bCustomCall = false;
	UInt32 aCustomRequestNum = 0;
	bool bIsAPICallResponse = false;
	const char* aPluginName = nil;
    // if this is the auth case or custom call case, we need to do some checks
    for (i=0; i< 10; i++)
    {
        object = &message->obj[i];
        UInt32 objType = DSGetLong( &object->type, direction );
		char* method;
		
		switch ( objType )
		{
			case kAuthMethod:
				// check for two-way random special case before we start swapping stuff
				method = (char *)message + DSGetLong( &object->offset, direction );
				if ( strcmp(method, kDSStdAuth2WayRandom) == 0 )
					isTwoWay = true;
				break;
			case kCustomRequestCode:
				//check for Custom Call special casing
				bCustomCall = true;
				aCustomRequestNum = DSGetLong( &object->count, direction );
				break;
			case ktNodeRef:
				//need to determine the nodename for discrimination of duplicate custom call codes - server
				aNodeRef = (UInt32)DSGetLong( &object->count, direction );
				break;
			case kResult:
				bIsAPICallResponse = true;
				break;
		}
    } // for (i=0; i< 10; i++)
	
	if ( bCustomCall && aCustomRequestNum != 0 && aNodeRef != 0 )
	{
		aPluginName = dsGetPluginNamePriv( aNodeRef, getpid() );
	}

    // swap objects
    for (i=0; i< 10; i++)
    {
        object = &message->obj[i];

        if (object->type == 0)
            continue;
            
        UInt32 objType = DSGetAndSwapLong(&object->type, direction);
        DSSwapLong(&object->count, direction);
        UInt32 objOffset = DSGetAndSwapLong(&object->offset, direction);
        DSSwapLong(&object->used, direction);
        UInt32 objLength = DSGetAndSwapLong(&object->length, direction);
            
        DSSwapObjectData(objType, (char *)message + objOffset, objLength, (!isTwoWay), bCustomCall, aCustomRequestNum, (const char*)aPluginName, bIsAPICallResponse, direction);
    }
    
#ifdef DUMP_BUFFER
    if (direction == kDSSwapNetworkToHostOrder)
        fprintf(gDumpFile, "\n\nBuffer in Host order (post Swap)\n");
    else
        fprintf(gDumpFile, "\n\nBuffer in Network order (post Swap)\n");
    DumpBuf(message->data, bufSize);
    fflush(stdout);
#endif
}