コード例 #1
0
ファイル: kernel_api.c プロジェクト: GodFox/magx_kernel_xpixl
/*
 * EvGetEventClassName() finds the class name string  associated with an event
 * class ID.  This function works only locally because all event classes
 * should be known locally.
 *
 * If the event group cound not be found -EEXIST will be returned.  If
 * the class identified by className is not registered the -ESRCH will
 * be returned.  Else "class" will be filled with the unique class
 * ID assiged to className and a zero will be returned to indicates 
 * success.
 */
int
EvGetEventClassName(EvGroupID_t groupID, EvClassID_t classID, char *className)
{
	EvGroupInfo_t *EGroup;
	EvClassInfo_t *HashBase;
	unsigned long Flags;
	int RetVal;

	/* Get the group info pointer and return with it locked. */
	if ((RetVal = EvLockAndGetGroup(groupID, EV_ACCESS_IGNORE,
					EAC_NONE, &Flags,
					EV_LOCK_GROUP_READ, &EGroup))) {
		return RetVal;
	}

	HashBase = EvGetHashBase(EGroup, classID);

	while (HashBase->EciNext) {
		if (HashBase->EciClass == classID) {
			strncpy(className, HashBase->EciName, 16);
			read_unlock_irqrestore(&EGroup->EgiLock, Flags);
			return EV_NOERR;
		}
		HashBase = HashBase->EciNext;
	}

	read_unlock_irqrestore(&EGroup->EgiLock, Flags);
	return -EV_ERROR_CLASS_EXISTS;
}
コード例 #2
0
ファイル: access_api.c プロジェクト: GodFox/magx_kernel_xpixl
int
EvSetClassAccessCode(EvGroupID_t groupID, EvClassID_t classID,
		     EvAccess_t oldCode, EvAccess_t newCode)
{
	EvGroupInfo_t *EGroup;
	EvClassInfo_t *HashBase;
	EvClassInfo_t *ClassBase;
	EvDestBase_t *EventBase;
	unsigned long Flags;

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

	HashBase = EvGetHashBase(EGroup, classID);

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

	if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase))==NULL) {
		spin_unlock_irqrestore(&HashBase->EciLock, Flags);
		return -EV_ERROR_CLASS_EXISTS;
	}

	if (EvCheckAccessCode(ClassBase->EciAccessCode, oldCode)) {
		spin_unlock_irqrestore(&HashBase->EciLock, Flags);
		return -EV_ERROR_CLASS_ACCESS;
	}

	ClassBase->EciAccessCode = newCode;
	spin_unlock_irqrestore(&HashBase->EciLock, Flags);
	return EV_NOERR;
}
コード例 #3
0
/*
 * Connection daemon has recieved a message from the event master
 * that a new class is available for this member.  This function
 * registers that new class.
 */
int
EvRemoteRegisterEventClass(EvGroupID_t groupID, char *className,
                           EvAccess_t groupAccessCode,
                           EvAccess_t classAccessCode,
                           int error, EvClassID_t classID)
{
    EvGroupInfo_t *EGroup;
    EvPendRem_t *Pend;
    EvClassInfo_t *HashBase;
    unsigned long Flags;
    int RetVal;

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

    write_lock(&EGroup->EgiLock);
    read_unlock(&EvGroupLock);

    /* Pend the pending control struct for this ID.
     *
     * If Pend is NULL then this is the master reporting a new event
     * class.
     */
    if ((Pend = EvFindPendEntry(EGroup, EV_REM_REGISTER_EVENT_CLASS,
                                groupAccessCode, classAccessCode, 0, 0,
                                strlen(className)+1, className)) != NULL) {
        /* Fill in the return values. */
        Pend->PrRetInfo.EpInfo[0] = error;
        Pend->PrRetInfo.EpInfo[1] = classID;

        /* Wake up the requester. */
        wake_up_interruptible(&Pend->PrWaitQ);

        write_unlock_irqrestore(&EGroup->EgiLock, Flags);
        return EV_NOERR;
    }

    /* Register a new event class on a group member for the master. */
    HashBase = EvGetHashBase(EGroup, classID);

    while (HashBase->EciNext != NULL) {
        HashBase = HashBase->EciNext;
    }

    RetVal=EvFillInHashInfo(HashBase, classAccessCode, className, &classID);

    write_unlock_irqrestore(&EGroup->EgiLock, Flags);
    return RetVal;
}
コード例 #4
0
ファイル: kernel_api.c プロジェクト: GodFox/magx_kernel_xpixl
/*
 * 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;
}
コード例 #5
0
ファイル: kernel_api.c プロジェクト: GodFox/magx_kernel_xpixl
/*
 * 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;
}
コード例 #6
0
ファイル: kernel_api.c プロジェクト: GodFox/magx_kernel_xpixl
int
EvInternalUnRegisterEventClass(EvGroupInfo_t *eGroup, EvClassID_t classID,
			    EvAccess_t accessCode)
{
	EvClassInfo_t *HashBase;
	EvClassInfo_t* HashDel;

	HashBase = EvGetHashBase(eGroup, classID);

	/* Does this hash have any classes assigned? */
	if (HashBase->EciNext == NULL) {
		return -EV_ERROR_CLASS_EXISTS;
	}

	/* Is the top element his class? */
	if (HashBase->EciClass == classID) {
		/* If subscribers use count is not zero then return error. */
		if (HashBase->EciUseCount != 0) {
			return -EV_ERROR_CLASS_BUSY;
		}

		if (EvCheckAccessCode(HashBase->EciAccessCode, accessCode)) {
			return -EV_ERROR_CLASS_ACCESS;
		}

		HashDel = HashBase->EciNext;

		HashBase->EciClass = HashDel->EciClass;
		strncpy(HashBase->EciName, HashDel->EciName, 16);
		HashBase->EciEventQ = HashDel->EciEventQ;
		HashBase->EciNext = HashDel->EciNext;

		goto EvDelHashInfo;
	}

	HashDel = HashBase->EciNext;

	while(HashDel->EciNext != NULL) {
		if (HashDel->EciClass == classID) {
			break;
		}
		HashBase = HashDel;
		HashDel = HashDel->EciNext;
	}

	if (HashDel->EciNext == NULL) {
		return -EV_ERROR_CLASS_EXISTS;
	}

	if (HashDel->EciUseCount != 0) {
		return -EV_ERROR_CLASS_BUSY;
	}

	if (EvCheckAccessCode(HashDel->EciAccessCode, accessCode)) {
		return -EV_ERROR_CLASS_ACCESS;
	}

	HashBase->EciNext = HashDel->EciNext;
	
EvDelHashInfo:
	/* Now reaquire the Group lock decrement the use count and send 
	 * remote packets.
	 */
	eGroup->EgiUseCount--;

	/* If this is a master send remove packets to all members. */
	if (eGroup->EgiType == EG_MASTER) {
		EvSendUnRegClassToMembers(eGroup, classID, accessCode);
	}

	if (HashDel->EciEventQ) {
		kfree(HashDel->EciEventQ);
	}

	kfree(HashDel);

	return EV_NOERR;
}
コード例 #7
0
ファイル: kernel_api.c プロジェクト: GodFox/magx_kernel_xpixl
/*
 * The EvRegisterEventClass() function registers the className string as the
 * identifier of an event class and returns a unique token to identify that
 * class.  The class is created as a part of an event group.
 *
 * If the event group is local then the event class is created as a part
 * of the local events and can be used only on the registering system.  If
 * this system is the master for an event group then a local identity is
 * created on this system and notification is sent to remote systems to
 * inidcate this event has been created.  If this event group is a member
 * on this system then the master is told to register this event class and
 * return the class ID and then a local copy of the registeration is made.
 *
 * If the event group defined by groupID does not exist then -EEXIST is
 * returned and no class is registered.  If the event class defined by
 * className already exists -EBUSY is returned and not class is registered.
 * returned.  If the kernel could not allocate enough memory for the
 * controling data structures -ENOSPC is returned and not class is
 * registered.  Otherwise the class identified by className is registered,
 * a unique ID is allocated and placed in the class parameter and a
 * zero is returned to indicate success.
 */
int
EvRegisterEventClass(EvGroupID_t groupID, char *className,
		     EvAccess_t groupAccessCode, EvAccess_t classAccessCode,
		     EvClassID_t *classID)
{
	EvGroupInfo_t *EGroup;
	EvClassInfo_t *HashBase;
	unsigned long Flags;
	int RetVal;

	/* Get the group info pointer and return with it locked. */
	if ((RetVal = EvLockAndGetGroup(groupID, EV_ACCESS_CHECK,
					groupAccessCode, &Flags,
					EV_LOCK_GROUP_WRITE, &EGroup))) {
		return RetVal;
	}

	/* Check to see if the class already exists */
	if (EvCheckEventClass(EGroup, className, classID) > -1) {
		write_unlock_irqrestore(&EGroup->EgiLock, Flags);
		return -EV_ERROR_CLASS_EXISTS;
	}

	/* If the event class is not a local one then send a register to
	 * the remote master.  The remote master returns the class ID.
	 */
	if ((EGroup->EgiType == EG_MEMBER) && EGroup->EgiNextClass) {
		if ((RetVal = EvSendRegEventClass(EGroup, className,
						  groupAccessCode,
						  classAccessCode,
						  classID, &Flags)) < 0) {
			write_unlock_irqrestore(&EGroup->EgiLock, Flags);
			return RetVal;
		}
	} else {
		/* Class is locally assigned */
		*classID = EGroup->EgiNextClass++;

		/* If this is an event master then send class create event. */
		if (EGroup->EgiType == EG_MASTER) {
			if ((RetVal = EvSendRegClassToMembers(EGroup, className,
					        groupAccessCode,
						classAccessCode, *classID))) {
			write_unlock_irqrestore(&EGroup->EgiLock, Flags);
			return RetVal;
			}
		}
	}

	HashBase = EvGetHashBase(EGroup, *classID);

	while (HashBase->EciNext != NULL) {
		HashBase = HashBase->EciNext;
	}

	RetVal=EvFillInHashInfo(HashBase, classAccessCode, className, classID);

	EGroup->EgiUseCount++;

	write_unlock_irqrestore(&EGroup->EgiLock, Flags);
	return RetVal;
}
コード例 #8
0
int
EvRemoteSendEvent(EvUserID_t senderID, EvGroupID_t memberID, EvPri_t pri,
                  EvGroupID_t groupID, EvClassID_t classID, EvEventID_t eventID,
                  EvAccess_t accessCode,
                  int info0, int info1, int info2, int info3,
                  int dataLen, void *data)
{
    EvGroupInfo_t *EGroup;
    EvDestBase_t *EventBase;
    EvClassInfo_t *HashBase;
    EvClassInfo_t *ClassBase;
    unsigned long Flags;
    int RetVal;

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

    /* If this a remote gen to the master then echo it back to
     * all members.
     */
    if (EGroup->EgiType == EG_MASTER) {
        if (EGroup->EgiGroupDest.EdID != 0) {
            RetVal = EvGroupSendEvent(senderID, pri,
                                      EGroup->EgiID, EGroup->EgiMemberID,
                                      accessCode, classID, eventID,
                                      info0, info1, info2, info3,
                                      &EGroup->EgiGroupDest, dataLen, data);
            if (RetVal) {
                read_unlock_irqrestore(&EvGroupLock, Flags);
                return RetVal;
            }
        }
    }

    /* If the memberID issuing the event is the same as the member
     * id of this system then we have been echoed back an event
     * we sent tot he master.  Ignore it.
     */
    if ((EGroup->EgiType == EG_MEMBER) &&
            (EGroup->EgiMemberID == memberID)) {
        read_unlock_irqrestore(&EvGroupLock, Flags);
        return EV_NOERR;
    }

    HashBase = EvGetHashBase(EGroup, classID);

    if ((EventBase = EvFindEventBase(classID, HashBase, &ClassBase))==NULL) {
        read_unlock_irqrestore(&EvGroupLock, Flags);
        return -EV_ERROR_CLASS_EXISTS;
    }

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

    RetVal = _EvSendEvent(EventBase, senderID, pri, groupID, memberID, classID,
                          eventID, info0, info1, info2, info3, dataLen, data);

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