/**
 * 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);
  }
示例#3
0
文件: semshm.cpp 项目: vedraiyani/GDL
  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);
}