Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Kernel - System.c
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/*   -------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, Andrew Aye.  All Rights Reserved.
    This software is free for non-commercial use.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
      following conditions are met:
        Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
        Redistribution in binary form must reproduce this copyright notice, this list of conditions and the following disclaimers in the documentation and other materials
          provided with the distribution.
    The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
    The intellectual property rights of the algorithms used reside with Andrew Aye.
    You may not use this software, in whole or in part, in support of any commercial product without the express written consent of the author.
    There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/* == Kernel ============================================================================================================================================================ */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- tgKN_Notify_Start ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_NOTIFY_ID tgKN_Notify_Start( TgKN_FCN_NOTIFY_CALLBACK psFCN, C_TgUINTPTR uiParam0, TgUINT32 uiMSG )
{
    TgUINT32                            uiCount, uiHash;
    TgSINT32                            iFree_Index;

    tgCM_UTM_SN_Lock_Spin( &g_sKN_Notfiy_Lock.m_sLock );

    /* Check for a free entry */
    if (0 > g_iKN_Notfiy_Free_Index)
    {
        TgCRITICAL_MSGF( 0, TgT( "%-16.16s(%-32.32s): Exceeded number of notification entries.\n" ), TgT("Kernel"), TgT("Notify") );
        tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
        return (KTgKN_NOTIFY_ID__INVALID);
    };

    /* Check for a possible hash collision */
    uiHash = uiMSG % KTgHASH_MD_SIZE;
    uiCount = 0;
    do
    {
        if (0 > g_aiKN_Notify_List[uiHash] || uiMSG == g_auiKN_Notify_MSG[g_aiKN_Notify_List[uiHash]])
        {
            break;
        };

        uiHash = (uiHash + 1) % KTgHASH_MD_SIZE;
    }
    while (++uiCount < KTgHASH_MD_SIZE);

    /* Make sure the hash table has not been filled */
    if (KTgHASH_MD_SIZE == uiCount)
    {
        TgCRITICAL_MSGF( 0, TgT( "%-16.16s(%-32.32s): Exceeded notification hash table.\n" ), TgT("Kernel"), TgT("Notify") );
        tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
        return (KTgKN_NOTIFY_ID__INVALID);
    };

    /* Take the first free element and forward the global free index */
    iFree_Index = g_iKN_Notfiy_Free_Index;
    g_iKN_Notfiy_Free_Index = g_aiKN_Notify_Next[g_iKN_Notfiy_Free_Index];

    /* This is the first function to register for this specific message (hash) */
    if (0 > g_aiKN_Notify_List[uiHash])
    {
        g_aiKN_Notify_List[uiHash] = iFree_Index;
    }
    /* We have existing functions registered for this message, add this new entry to the linked list */
    else
    {
        TgSINT32                            iIndex = g_aiKN_Notify_List[uiHash];

        while (0 <= g_aiKN_Notify_Next[iIndex])
        {
            iIndex = g_aiKN_Notify_Next[iIndex];
        };

        g_aiKN_Notify_Next[iIndex] = iFree_Index;
    };

    /* Fill in the data for the notification */
    g_asKN_Notify_Data[iFree_Index].m_psFCN = psFCN;
    g_asKN_Notify_Data[iFree_Index].m_uiParam0 = uiParam0;
    g_auiKN_Notify_MSG[iFree_Index] = uiMSG;
    g_aiKN_Notify_Next[iFree_Index] = -1;
    tgInit_KN_NOTIFY_ID( &g_atiKN_Notify[iFree_Index], iFree_Index );

    tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
    return (g_atiKN_Notify[iFree_Index]);
}


/* ---- tgKN_Notify_End ------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_Notify_End( C_TgKN_NOTIFY_ID tiNotify )
{
    TgUINT32                            uiCount, uiMSG;
    TgUINTXX                            uiHash;
    P_TgSINT32                          piIndex;

    tgCM_UTM_SN_Lock_Spin( &g_sKN_Notfiy_Lock.m_sLock );

    /* Make sure the entry is still valid */
    if (tiNotify.m.iI >= KTgKN_MAX_NOTIFY_ENTRIES || TgTRUE != tgEQ_KN_NOTIFY_ID( tiNotify, g_atiKN_Notify[tiNotify.m.iI] ))
    {
        tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
        return (KTgE_FAIL);
    };

    /* Find the hash listing for the message attached to this entry */
    uiHash = g_auiKN_Notify_MSG[tiNotify.m.iI] % KTgHASH_MD_SIZE;
    uiMSG = g_auiKN_Notify_MSG[tiNotify.m.iI];
    uiCount = 0;
    do
    {
        if (0 <= g_aiKN_Notify_List[uiHash] && uiMSG == g_auiKN_Notify_MSG[g_aiKN_Notify_List[uiHash]])
        {
            break;
        };

        uiHash = (uiHash + 1) % KTgHASH_MD_SIZE;
    }
    while (++uiCount < KTgHASH_MD_SIZE);

    /* Make sure the hash table has not been filled */
    if (KTgHASH_MD_SIZE == uiCount)
    {
        tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
        return (KTgE_FAIL);
    };

    /* Remove entry from the link list of handlers for the message */
    piIndex = g_aiKN_Notify_List + uiHash;
    while (tiNotify.m.iI != *piIndex)
    {
        piIndex = g_aiKN_Notify_Next + *piIndex;
    };
    *piIndex = g_aiKN_Notify_Next[tiNotify.m.iI];

    /* Add the entry back into the free list */
    g_aiKN_Notify_Next[tiNotify.m.iI] = g_iKN_Notfiy_Free_Index;
    g_iKN_Notfiy_Free_Index = tiNotify.m.iI;

    tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
    return (KTgS_OK);
}


/* ---- tgKN_Notify_MSG ------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  1: the MSG value ( must be unique )                                                                                                                                   */
/*  2: uiParam1 - Generic 32bit Parameter                                                                                                                                 */
/*  3: uiParam2 - Generic 32bit Parameter                                                                                                                                 */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_Notify_MSG( C_TgUINT32 uiMSG, C_TgUINT32 uiParam1, C_TgUINT32 uiParam2 )
{
    TgUINTXX                            uiHash;
    TgUINT32                            uiCount;
    TgSINT32                            iIndex;

    tgCM_UTM_SN_Lock_Spin( &g_sKN_Notfiy_Lock.m_sLock );

    /* Find the hash listing for the message attached to this entry */
    uiHash = uiMSG % KTgHASH_MD_SIZE;
    uiCount = 0;
    do
    {
        if (0 <= g_aiKN_Notify_List[uiHash] && uiMSG == g_auiKN_Notify_MSG[g_aiKN_Notify_List[uiHash]])
        {
            break;
        };

        uiHash = (uiHash + 1) % KTgHASH_MD_SIZE;
    }
    while (++uiCount < KTgHASH_MD_SIZE);

    /* Make sure the hash table has not been filled */
    if (KTgHASH_MD_SIZE == uiCount)
    {
        tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
        return (KTgE_FAIL);
    };

    iIndex = g_aiKN_Notify_List[uiHash];
    do
    {
        g_asKN_Notify_Data[iIndex].m_psFCN( g_asKN_Notify_Data[iIndex].m_uiParam0, uiParam1, uiParam2 );
    }
    while (0 <= (iIndex = g_aiKN_Notify_Next[iIndex]));

    tgCM_UTM_SN_Signal( &g_sKN_Notfiy_Lock.m_sLock );
    return (KTgS_OK);
}