Example #1
0
/*
 * EvGetEvent() retrieves an event from the event queue assigned to
 * the user id.
 *
 * If the user ID passed in is not a registed user then -ENOENT is
 * returned.  If there are no pending events and waitflag is not
 * set then -EAGAIN is returned.  If there are no events and waitflag
 * is set then the kernel thread associated with the user ID is
 * put to sleep.
 *
 * Otherwise the event packet pointer is placed in packet and a zero
 * is returned to indicate success.
 */
int
EvGetEvent(EvUserID_t userID, int waitFlag, EvPacket_t **packet)
{
	EvPacket_t *TmpPacket;
	EvKernelInfo_t *EventUser;
	unsigned long Flags;

	read_lock_irqsave(&EvUsersLock, Flags);

	/* Make sure this is a valile user ID. */
	if ((EventUser = EvCheckUser(userID)) == NULL) {
		read_unlock_irqrestore(&EvUsersLock, Flags);
		*packet = NULL;
		return -EV_ERROR_USER_EXISTS;
	}

	spin_lock(&EventUser->EkiLock);
	read_unlock(&EvUsersLock);

	for (;;) {
		TmpPacket = EventUser->EkiHead;

		/* If there is a queued packet then get it and return. */
		if (TmpPacket) {
			EventUser->EkiHead = TmpPacket->EpNext;
			if (EventUser->EkiHead == NULL) {
				EventUser->EkiTail = NULL;
			}
			EventUser->EkiQCount--;
			spin_unlock_irqrestore(&EventUser->EkiLock, Flags);
			*packet = TmpPacket;
			return EV_NOERR;
		}

		/* No queued packet and wait flag is not set then return
		 * with a try again later indication.
		 */
		if (!waitFlag) {
			spin_unlock_irqrestore(&EventUser->EkiLock, Flags);
			*packet = NULL;
			return -EV_ERROR_NO_EVENT;
		}

		/* Other wise sleep waiting for ane event to arrive. */
		spin_unlock_irqrestore(&EventUser->EkiLock, Flags);
		interruptible_sleep_on(&EventUser->EkiWaitQ);
		spin_lock_irqsave(&EventUser->EkiLock, Flags);
	}
}
Example #2
0
int
EvSubscribeGroupEvents(EvUserID_t userID,
                       EvGroupID_t groupID, EvAccess_t accessCode,
                       int (*kernelCB)(EvUserID_t, int, EvGroupID_t,
                                       EvGroupID_t, EvClassID_t, EvEventID_t,
                                       int, int, int, int, int, void *))
{
    EvKernelInfo_t *EventUser;
    EvGroupInfo_t *EGroup;
    unsigned long Flags;

    read_lock_irqsave(&EvUsersLock, Flags);
    if ((EventUser = EvCheckUser(userID)) == NULL) {
        read_unlock_irqrestore(&EvUsersLock, Flags);
        return -EV_ERROR_USER_EXISTS;
    }

    write_lock(&EvGroupLock);
    read_unlock(&EvUsersLock);

    if ((EGroup = EvGetGroupBase(groupID)) == NULL) {
        write_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_GROUP_EXIST;
    }

    /* Check the access code for the group. */
    if (EvCheckAccessCode(EGroup->EgiAccessCode, accessCode)) {
        write_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_GROUP_ACCESS;
    }

    /* Check that there are no current control processes. */
    if (EGroup->EgiGroupDest.EdID != 0) {
        write_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_GROUP_BUSY;
    }

    EGroup->EgiGroupDest.EdPri = 0;		/* Not used. */
    EGroup->EgiGroupDest.EdID = userID;
    EGroup->EgiGroupDest.EdUinfo = NULL;
    EGroup->EgiGroupDest.EdCB = kernelCB;
    EGroup->EgiGroupDest.EdKinfo = EventUser;

    EGroup->EgiUseCount++;

    write_unlock_irqrestore(&EvGroupLock, Flags);
    return EV_NOERR;
}
Example #3
0
int
EvUnSubscribeGroupEvents(EvUserID_t userID, EvGroupID_t groupID)
{
    EvKernelInfo_t *EventUser;
    EvGroupInfo_t *EGroup;
    unsigned long Flags;

    read_lock_irqsave(&EvUsersLock, Flags);
    if ((EventUser = EvCheckUser(userID)) == NULL) {
        read_unlock_irqrestore(&EvUsersLock, Flags);
        return -EV_ERROR_USER_EXISTS;
    }

    write_lock(&EvGroupLock);
    read_unlock(&EvUsersLock);

    if ((EGroup = EvGetGroupBase(groupID)) == NULL) {
        write_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_GROUP_EXIST;
    }

    /* Check that there are no current control processes. */
    if (EGroup->EgiGroupDest.EdID != userID) {
        write_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_GROUP_ACCESS;
    }

    EGroup->EgiGroupDest.EdID = 0;
    EGroup->EgiGroupDest.EdUinfo = NULL;
    EGroup->EgiGroupDest.EdCB = NULL;
    EGroup->EgiGroupDest.EdKinfo = NULL;

    EGroup->EgiUseCount--;

    write_unlock_irqrestore(&EvGroupLock, Flags);

    return EV_NOERR;
}
Example #4
0
/*
 * EvUnSubscribeEvent() removes the user id from the list of subscribers
 * waiting for the particular event to occur.
 *
 * If the user ID does not indicate a currently registered user then
 * -ENOENT is returned.  If the event group is not a currently registered
 * group then -EEXIST is returned.  If the class in not found in the this
 * of currently know classes then -EINVAL is returned.  If the user is
 * not currently subscribed to recieve the event then -EBUSY is returned.
 *
 * Otherwise the subscription is removed and a zero is returned to
 * indicate susccess.
 */
int
EvUnSubscribeEvent(EvUserID_t userID, EvGroupID_t groupID,
		   EvClassID_t classID, EvEventID_t eventID)
{
	EvDest_t *EventDestP = NULL;
	EvDest_t *FreeDest = NULL;
	EvDestBase_t *EventBase;
	EvDestBase_t *LastEventBase = NULL;
	EvKernelInfo_t *EventUser;
	EvGroupInfo_t *EGroup;
	EvClassInfo_t *HashBase;
	EvClassInfo_t *ClassBase;
	unsigned long Flags;

	/* Check the user id. */
	read_lock_irqsave(&EvUsersLock, Flags);
	if ((EventUser = EvCheckUser(userID)) == NULL) {
		read_unlock_irqrestore(&EvUsersLock, Flags);
		return -EV_ERROR_USER_EXISTS;
	}

	read_lock(&EvGroupLock);
	read_unlock(&EvUsersLock);

	/* Get the base event group information. */
	if ((EGroup = EvGetGroupBase(groupID)) == NULL) {
		read_unlock_irqrestore(&EvGroupLock, Flags);
		return -EV_ERROR_GROUP_EXIST;
	}

	HashBase = EvGetHashBase(EGroup, classID);

	/* Find the top level entry for this class of events. */
	if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase)) == NULL){
		read_unlock_irqrestore(&EvGroupLock, Flags);
		return -EV_ERROR_CLASS_EXISTS;
	}

	spin_lock(&ClassBase->EciLock);
	read_unlock(&EvGroupLock);

	/* search until the event is found in this catagory or until the
	 * last blank element on the list if found.
	 */
	while (EventBase->EdbNext != NULL) {
		if (EventBase->EdbEvent == eventID) {
			EventDestP = &EventBase->EdbDestQ;
			break;
		}

		LastEventBase = EventBase;
		EventBase = EventBase->EdbNext;
	}

	/* If event type not found then the user process was obviously not
	 * registered for this event.
	 */
	if (EventDestP == NULL) {
		spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
		return -EV_ERROR_CLASS_NO_SUB;
	}

	if (EventDestP->EdID == userID) {
		if (EventDestP->EdNext == NULL) {
			/* This is the only element on the list so it
			 * will be removed below. */
			goto EvUnRegFreeBase;
		}

		EventDestP->EdUinfo = EventDestP->EdNext->EdUinfo;
		EventDestP->EdCB = EventDestP->EdNext->EdCB;
		EventDestP->EdID = EventDestP->EdNext->EdID;
		EventDestP->EdKinfo = EventDestP->EdNext->EdKinfo;
		FreeDest = EventDestP->EdNext;
		EventDestP->EdNext = EventDestP->EdNext->EdNext;

		goto EvUnRegFreeBase;
	}
		
	/* Allways search one ahead to help with single link list removal. */
	while (EventDestP->EdNext->EdNext != NULL) {
		if (EventDestP->EdNext->EdID == userID) {
			FreeDest = EventDestP->EdNext;
			EventDestP->EdNext = EventDestP->EdNext->EdNext;

			goto EvUnRegFreeBase;
		}
		EventDestP = EventDestP->EdNext;
	}

	/* Entry not found in list. */
	spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
	return -EV_ERROR_CLASS_NO_SUB;

EvUnRegFreeBase:
	EventBase->EdbUseCount--;

	if (EventBase->EdbUseCount == 0) {
		/* Nobody is registered to receive this event. */
		if (LastEventBase == NULL) {
			/* Free the top element */
			EventBase->EdbEvent = EventBase->EdbNext->EdbEvent;
			EventBase->EdbUseCount = EventBase->EdbNext->EdbUseCount;
			EventBase->EdbDestQ = EventBase->EdbNext->EdbDestQ;
			LastEventBase = EventBase->EdbNext;
			EventBase->EdbNext = LastEventBase->EdbNext;
			kfree(LastEventBase);
		} else {
			LastEventBase->EdbNext = EventBase->EdbNext;
			kfree(EventBase);
		}
	}

	ClassBase->EciUseCount--;
	kfree(FreeDest);

	spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
	return EV_NOERR;
}
Example #5
0
/*
 * EvSubscribeEvent() subscribes a kernel component to recieve
 * an event.  If the event call back function kernelCB is specified
 * events will be delivered by calling this function.  Otherwise 
 * events will be placed on an internal event queue and the queue must
 * be polled using the EvGetEvent function.
 *
 * This function subscribes to an event localy.  It does not attempt to
 * inform a remote master that a subscriber has been attached.  This
 * should be added in a later version of the function.
 */
int
EvSubscribeEvent(EvUserID_t userID, EvPri_t pri,
		 EvGroupID_t groupID, EvClassID_t classID,
		 EvEventID_t eventID, EvAccess_t accessCode,
		 int (*kernelCB)(EvUserID_t, EvPri_t, EvGroupID_t,
				 EvGroupID_t, EvClassID_t, EvEventID_t,
				 int, int, int, int, int, void *))
{
	EvDest_t *EventDestP = NULL;
	EvDest_t *TmpDestP = NULL;
	EvDest_t *LastEventDestP = NULL;
	EvDestBase_t *EventBase;
	EvKernelInfo_t *EventUser;
	EvGroupInfo_t *EGroup;
	EvClassInfo_t *HashBase;
	EvClassInfo_t *ClassBase;
	unsigned long Flags;

	/* Check the user ID for validity. */
	read_lock_irqsave(&EvUsersLock, Flags);
	if ((EventUser = EvCheckUser(userID)) == NULL) {
		read_unlock_irqrestore(&EvUsersLock, Flags);
		return -EV_ERROR_USER_EXISTS;
	}

	/* Assume the Event user returned status will no change during
	 * the life of this request.
	 */
	read_lock(&EvGroupLock);
	read_unlock(&EvUsersLock);

	/* Get the event group pointer. */
	if ((EGroup = EvGetGroupBase(groupID)) == NULL) {
		read_unlock_irqrestore(&EvGroupLock, Flags);
		return -EV_ERROR_GROUP_EXIST;
	}

	HashBase = EvGetHashBase(EGroup, classID);

	/* Find the top level entry for this class of events. */
	if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase)) == NULL){
		read_unlock_irqrestore(&EvGroupLock, Flags);
		return -EV_ERROR_CLASS_EXISTS;
	}

	spin_lock(&ClassBase->EciLock);
	read_unlock(&EvGroupLock);

	/* Check permissions. */
	if (EvCheckAccessCode(ClassBase->EciAccessCode, accessCode)) {
		spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
		return -EV_ERROR_CLASS_ACCESS;
	}

	/* search until the event is found in this catagory or until the
	 * last blank element on the list if found.
	 */
	while (EventBase->EdbNext != NULL) {
		if (EventBase->EdbEvent == eventID) {
			EventDestP = &EventBase->EdbDestQ;
			break;
		}
		EventBase = EventBase->EdbNext;
	}

	/* If no destination pointer has been identified for a chain
	 * search then this event type has not yet been registered by anybody
	 * so fill in the last empty list element and create a new empty one
	 * to inidcate end of list.
	 */
	if (EventDestP == NULL) {
		EventBase->EdbEvent = eventID;
		EventBase->EdbUseCount = 0;

		/* Create the next empty element to indicate end of list. */
		if ((EventBase->EdbNext = kmalloc(sizeof(EvDestBase_t),
							GFP_ATOMIC)) == NULL) {
			spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
			return -EV_ERROR_MEM_ALLOC;
		}

		EventBase->EdbNext->EdbNext = NULL;

		EventDestP = &EventBase->EdbDestQ;
		EventDestP->EdNext = kmalloc(sizeof(EvDest_t), GFP_ATOMIC);
		EventDestP->EdNext->EdNext = NULL;

		 goto EvFillInKernelRequestPacket;
	}

	/* Now search to see if this file descriptor already has registered
	 * for this event type.
	 */
	while (EventDestP->EdNext != NULL) {
		if (EventDestP->EdID == userID) {
			spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
			return -EV_ERROR_CLASS_BUSY;
				
		}

		LastEventDestP = EventDestP;
		EventDestP = EventDestP->EdNext;
	}

	/* Now record the destination and create a new empty element to 
	 * indicate end of list.
	 */

	/* Most registrations go at the end of the list. */
	if ((LastEventDestP != NULL) && (LastEventDestP->EdPri >= pri)) {
		if ((EventDestP->EdNext = kmalloc(sizeof(EvDest_t),
							GFP_ATOMIC)) == NULL) {
			spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
			return -EV_ERROR_MEM_ALLOC;
		}

		EventDestP->EdNext->EdNext = NULL;
		goto EvFillInKernelRequestPacket;
	}

	EventDestP = &EventBase->EdbDestQ;

	/* Check the priority against the top element */
	if (EventDestP->EdPri >= pri) {
		/* Priority of event places it somewhere in the middle */
		while (EventDestP->EdNext->EdPri >= pri) {
			EventDestP = EventDestP->EdNext;
		}
	}

	if ((TmpDestP = kmalloc(sizeof(EvDest_t), GFP_ATOMIC)) == NULL) {
		spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
		return -EV_ERROR_MEM_ALLOC;
	}

	TmpDestP->EdPri = EventDestP->EdPri;
	TmpDestP->EdUinfo = EventDestP->EdUinfo;
	TmpDestP->EdCB = EventDestP->EdCB;
	TmpDestP->EdID = EventDestP->EdID;
	TmpDestP->EdKinfo = EventDestP->EdKinfo;
	TmpDestP->EdNext = EventDestP->EdNext;
	EventDestP->EdNext = TmpDestP;

EvFillInKernelRequestPacket:
	EventBase->EdbUseCount++;
	EventDestP->EdPri = pri;
	EventDestP->EdUinfo = NULL;
	EventDestP->EdID = userID;
	EventDestP->EdCB = kernelCB;

	EventDestP->EdKinfo = EventUser;

	ClassBase->EciUseCount++;

	spin_unlock_irqrestore(&ClassBase->EciLock, Flags);
	return EV_NOERR;
}