/** * down_interruptible - acquire the semaphore unless interrupted * @sem: the semaphore to be acquired * * Attempts to acquire the semaphore. If no more tasks are allowed to * acquire the semaphore, calling this function will put the task to sleep. * If the sleep is interrupted by a signal, this function will return -EINTR. * If the semaphore is successfully acquired, this function returns 0. */ int down_interruptible(struct semaphore *sem) { unsigned long flags; int result = 0; spin_lock_irqsave(&sem->lock, flags); if (likely(sem->count > 0)){ sem->count--; }else{ #ifdef CONFIG_MT_LOCK_DEBUG if(sem->owner == current){ char aee_str[40]; printk("[Warning!Recursive Semaphore!][%d:%s], down_interruptible:%s(0x%x)\n", current->pid, current->comm, sem->sem_name, sem); sprintf( aee_str, "Recursive SemLock:%s\n", current->comm); aee_kernel_warning( aee_str,"mtlock debugger\n"); dump_stack(); } #endif result = __down_interruptible(sem); } #ifdef CONFIG_MT_LOCK_DEBUG if(0 == sem->count) sem_set_owner(sem); #endif spin_unlock_irqrestore(&sem->lock, flags); return result; }
BaseGDL* sem_create(EnvT *e) { SizeT nParam = e->NParam(1); // 1 is the minimal number of parameter required DString name; e->AssureStringScalarPar(0, name); // IDL accepts null-string name int destroyIx = e->KeywordIx("DESTROY_SEMAPHORE"); bool destroyKWPresent = e->KeywordPresent(destroyIx); DLong destroy = 0; if (destroyKWPresent) { destroy = (*e->GetKWAs<DLongGDL>(0))[0]; } bool owner = true; #if defined(_WIN32) && !defined(__CYGWIN__) // TODO: Needs error handling with name length > 256 const char* cname = name.c_str(); WCHAR tname[256] = {0,}; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cname, strlen(cname), tname, 256); HANDLE sem = CreateSemaphoreW(NULL,1,1,tname); if (sem == NULL) { owner = false; return new DIntGDL(0); } #else sem_t *sem = sem_open(name.c_str(), O_CREAT | O_EXCL, 0666, 1); if (sem == SEM_FAILED) { // semaphore exists. make another one, locked (value=0) owner = false; if (errno == EEXIST) { sem = sem_open(name.c_str(), O_CREAT ,0666, 0); } if (sem == SEM_FAILED) { return new DIntGDL(0); } } #endif // Behavior for different values of DESTROY_SEMAPHORE: // DESTROY_SEMAPHORE | owner | other (== !owner) // ------------------+----------+----------- // not set | delete | ignore // != 0 | delete | delete // 0 | ignore | ignore sem_data_t data; data.sem = sem; sem_set_owner(data, owner); sem_set_deletable(data, (!destroyKWPresent && owner) || (destroy != 0)); sem_set_locked(data, false); sem_add(name, data); return new DIntGDL(1); }
BaseGDL* sem_create(EnvT *e) { SizeT nParam = e->NParam(1); // 1 is the minimal number of parameter required DString name; e->AssureStringScalarPar(0, name); // IDL accepts null-string name int destroyIx = e->KeywordIx("DESTROY_SEMAPHORE"); bool destroyKWPresent = e->KeywordPresent(destroyIx); DLong destroy = 0; if (destroyKWPresent) { destroy = (*e->GetKWAs<DLongGDL>(0))[0]; } bool owner = true; #ifdef _MSC_VER HANDLE sem = CreateSemaphore(NULL,1,1,name.c_str()); if (sem == NULL) { owner = false; return new DIntGDL(0); } #else sem_t *sem = sem_open(name.c_str(), O_CREAT | O_EXCL, 0666, 1); if (sem == SEM_FAILED) { owner = false; if (errno == EEXIST) { sem = sem_open(name.c_str(), 0); } if (sem == SEM_FAILED) { return new DIntGDL(0); } } #endif // Behavior for different values of DESTROY_SEMAPHORE: // DESTROY_SEMAPHORE | owner | other (== !owner) // ------------------+----------+----------- // not set | delete | ignore // != 0 | delete | delete // 0 | ignore | ignore sem_data_t data; data.sem = sem; sem_set_owner(data, owner); sem_set_deletable(data, (!destroyKWPresent && owner) || (destroy != 0)); sem_set_locked(data, false); sem_add(name, data); return new DIntGDL(1); }
/** * down_trylock - try to acquire the semaphore, without waiting * @sem: the semaphore to be acquired * * Try to acquire the semaphore atomically. Returns 0 if the mutex has * been acquired successfully or 1 if it it cannot be acquired. * * NOTE: This return value is inverted from both spin_trylock and * mutex_trylock! Be careful about this when converting code. * * Unlike mutex_trylock, this function can be used from interrupt context, * and the semaphore can be released by any task or interrupt. */ int down_trylock(struct semaphore *sem) { unsigned long flags; int count; spin_lock_irqsave(&sem->lock, flags); count = sem->count - 1; if (likely(count >= 0)){ sem->count = count; #ifdef CONFIG_MT_LOCK_DEBUG if(0 == sem->count) sem_set_owner(sem); #endif } spin_unlock_irqrestore(&sem->lock, flags); return (count < 0); }