Beispiel #1
0
void egbb_init(void) {

   // init

   Egbb->init = false;
   Egbb->load = false;
   Egbb->size = CacheSize;
   Egbb->piece_nb = 0;
   Egbb->read_hit = 0;
   Egbb->read_nb = 0;

   LibHandler = LOAD_LIB(EgbbLib);

   if (LibHandler != NULL) {

      send("egbb library loaded");

      load_egbb_ptr =    (load_egbb_5men)     GET_ENTRY(LibHandler,"load_egbb_5men");
      probe_egbb_ptr =   (probe_egbb_5men)    GET_ENTRY(LibHandler,"probe_egbb_5men");

      if (load_egbb_ptr == NULL)   my_fatal("egbb_init(): load_egbb_5men() not found\n");
      if (probe_egbb_ptr == NULL)  my_fatal("egbb_init(): probe_egbb_5men() not found\n");

      Egbb->init = true;
   }
}
Beispiel #2
0
/********************************************************************

    Function:       adi_fsd_cache_Write

    Description:    Unlock cache sector, signals to the cache that
                    the FSD has finished modifying block until next
                    read.

********************************************************************/
__ADI_FSD_CACHE_SECTION_CODE
u32 adi_fsd_cache_Write(
    ADI_FSD_CACHE_HANDLE    CacheHandle,
    u8                      *pData)
{
    u32 Result;
    PDD_FSD_CACHE_DEF *pCache;
    
    Result=ADI_DEV_RESULT_SUCCESS;
    pCache=(PDD_FSD_CACHE_DEF *)CacheHandle;
    
    if (pData)
    {
        PDD_FSD_CACHE_ENTRY *pEntry;
        
        /* locate beginning of enclosing data block */
        pEntry = GET_ENTRY(pData);
        
        pEntry->Locked--;
        pEntry->Modified=1;
        
        /* If Flush on Write flag is set flush buffer */
        if (pCache->Flags&ADI_FSD_CACHE_FLUSH_ON_WRITE)
        {
            Result=pdd_Transfer(
                pCache,
                pEntry,
                WRITE,
                0,
                0);
        }
    }
    
    return Result;
}
Beispiel #3
0
/**
 * Finds a RWEntry for the calling thread. This function must be called 
 * under synchronization. Returns NULL if entry for calling thread does not 
 * exist.
 */
STATIC RWEntry * RWLOCK_FindEntry(RWLock * lock) 
{
    int i;
    ThrID self = THREAD_Self();
    for (i=0; i<lock->entriesInUse; i++) {
        RWEntry * entry = GET_ENTRY(lock,i);
        if (entry->id == self) {
            return entry;
        }
    }    
    return NULL;
}
Beispiel #4
0
// Gets the minimum element
int heap_min(heap* h, void** key, void** value) {
    // Check the number of elements, abort if 0
    if (h->active_entries == 0)
        return 0;

    // Get the 0th element
    heap_entry* root = GET_ENTRY(0, h->table);

    // Set the key and value
    if (key) *key = root->key;
    if (value) *value = root->value;

    // Success
    return 1;
}
Beispiel #5
0
// Allows a user to iterate over all entries, e.g. to free() the memory
void heap_foreach(heap* h, void (*func)(void*,void*)) {
    // Store the current index and max index
    int index = 0;
    int entries = h->active_entries;

    heap_entry* entry;
    heap_entry* table = h->table;

    for (;index<entries;index++) {
        // Get the entry
        entry = GET_ENTRY(index,table);

        // Call the user function
        func(entry->key, entry->value);
    }
}
Beispiel #6
0
void heap_foreach_entry(heap* h, void (*func)(heap_entry*, void*), void* arg) {
    // Store the current index and max index
    int index = 0;
    int entries = h->active_entries;

    heap_entry* entry;
    void** map_table = h->mapping_table;

    for (;index<entries;index++) {
        // Get the entry
        entry = GET_ENTRY(index,map_table);

        // Call the user function
        func(entry, arg);
    }
}
Beispiel #7
0
/********************************************************************

    Function:       adi_fsd_cache_Release

    Description:    Unlock a sector without updating the modify flag,
                    this is used when a sector is read but not
                    modified. The caller has to execute either the
                    Write or Release function after a Read

********************************************************************/
__ADI_FSD_CACHE_SECTION_CODE
u32 adi_fsd_cache_Release(
    ADI_FSD_CACHE_HANDLE    CacheHandle,
    u8                      *pData)
{
    PDD_FSD_CACHE_DEF *pCache;
    PDD_FSD_CACHE_ENTRY *pEntry;

    pCache=(PDD_FSD_CACHE_DEF *)CacheHandle;
    
    if (pData)
    {
        /* locate beginning of enclosing data block */
        pEntry = GET_ENTRY(pData);
        pEntry->Locked--;
    }
    
    return ADI_DEV_RESULT_SUCCESS;
}
Beispiel #8
0
// Deletes the minimum entry in the heap
int heap_delmin(heap* h, void** key, void** value) {
    // Check there is a minimum
    if (h->active_entries == 0)
        return 0;

    // Load in the map table
    heap_entry* table = h->table;

    // Get the root element
    int current_index = 0;
    heap_entry* current = GET_ENTRY(current_index, table);

    // Store the outputs
    if (key) *key = current->key;
    if (value) *value = current->value;

    // Reduce the number of active entries
    h->active_entries--;

    // Get the active entries
    int entries = h->active_entries;

    // If there are any other nodes, we may need to move them up
    if (h->active_entries > 0) {
        // Move the last element to the root
        heap_entry* last = GET_ENTRY(entries,table);
        current->key = last->key;
        current->value = last->value;

        // Loop variables
        heap_entry* left_child;
        heap_entry* right_child;

        // Load the comparison function
        int (*cmp_func)(void*,void*) = h->compare_func;

        // Store the left index
        int left_child_index;

        while (left_child_index = LEFT_CHILD(current_index), left_child_index < entries) {
            // Load the left child
            left_child = GET_ENTRY(left_child_index, table);

            // We have a left + right child
            if (left_child_index+1 < entries) {
                // Load the right child
                right_child = GET_ENTRY((left_child_index+1), table);

                // Find the smaller child
                if (cmp_func(left_child->key, right_child->key) <= 0) {

                    // Swap with the left if it is smaller
                    if (cmp_func(current->key, left_child->key) == 1) {
                        SWAP_ENTRIES(current,left_child);
                        current_index = left_child_index;
                        current = left_child;

                    // Otherwise, the current is smaller
                    } else
                        break;

                // Right child is smaller
                } else {

                    // Swap with the right if it is smaller
                    if (cmp_func(current->key, right_child->key) == 1) {
                        SWAP_ENTRIES(current,right_child);
                        current_index = left_child_index+1;
                        current = right_child;

                    // Current is smaller
                    } else
                        break;

                }


            // We only have a left child, only do something if the left is smaller
            } else if (cmp_func(current->key, left_child->key) == 1) {
                SWAP_ENTRIES(current,left_child);
                current_index = left_child_index;
                current = left_child;

            // Done otherwise
            }  else
                break;

        }
    }

    // Check if we should release a page of memory
    int used_pages = entries / ENTRIES_PER_PAGE + ((entries % ENTRIES_PER_PAGE > 0) ? 1 : 0);

    // Allow one empty page, but not two
    if (h->allocated_pages / 2 > used_pages + 1 && h->allocated_pages / 2 >= h->minimum_pages) {
        // Get the new number of entries we need
        int new_size = h->allocated_pages / 2;

        // Map in a new table
        heap_entry* new_table = map_in_pages(new_size);

        // Copy the old entries, copy the entire pages
        memcpy(new_table, h->table, used_pages*PAGE_SIZE);

        // Cleanup the old table
        map_out_pages(h->table, h->allocated_pages);

        // Switch to the new table
        h->table = new_table;
        h->allocated_pages = new_size;
    }

    // Success
    return 1;
}
Beispiel #9
0
// Insert a new element
void heap_insert(heap *h, void* key, void* value) {
    // Check if this heap is not destoyed
    assert(h->table != NULL);

    // Check if we have room
    int max_entries = h->allocated_pages * ENTRIES_PER_PAGE;
    if (h->active_entries + 1 > max_entries) {
        // Get the new number of entries we need
        int new_size = h->allocated_pages * 2;

        // Map in a new table
        heap_entry* new_table = map_in_pages(new_size);

        // Copy the old entries, copy the entire pages
        memcpy(new_table, h->table, h->allocated_pages*PAGE_SIZE);

        // Cleanup the old table
        map_out_pages(h->table, h->allocated_pages);

        // Switch to the new table
        h->table = new_table;
        h->allocated_pages = new_size;
    }

    // Store the comparison function
    int (*cmp_func)(void*,void*) = h->compare_func;

    // Store the table address
    heap_entry* table = h->table;

    // Get the current index
    int current_index = h->active_entries;
    heap_entry* current = GET_ENTRY(current_index, table);

    // Loop variables
    int parent_index;
    heap_entry *parent;

    // While we can, keep swapping with our parent
    while (current_index > 0) {
        // Get the parent index
        parent_index = PARENT_ENTRY(current_index);

        // Get the parent entry
        parent = GET_ENTRY(parent_index, table);

        // Compare the keys, and swap if we need to
        if (cmp_func(key, parent->key) < 0) {
            // Move the parent down
            current->key = parent->key;
            current->value = parent->value;

            // Move our reference
            current_index = parent_index;
            current = parent;

        // We are done swapping
        }   else
            break;
    }

    // Insert at the current index
    current->key = key;
    current->value = value;

    // Increase the number of active entries
    h->active_entries++;
}
Beispiel #10
0
/**
 * Returns available RWEntry for the calling thread. Reallocates array
 * of thread entries if necessary. Obviously, this function must be called 
 * under synchronization. Returns NULL only if we run out of thread entries 
 * and memory allocation fails.
 */
STATIC RWEntry * RWLOCK_GetEntry(RWLock * lock) 
{
    int i;
    ThrID self = THREAD_Self();
    RWEntry * empty = NULL;  /* vacant empty entry */

    /* 
     * try to find existing entry for this thread. At the same time
     * pick up the first available empty slot.
     */
    for (i=0; i<lock->entriesInUse; i++) {
        RWEntry * entry = GET_ENTRY(lock,i);
        if (entry->id == self) {
            return entry;
        } else if (!empty && !entry->id) {
            empty = entry;
        }
    }

    /* 
     * we didn't find existing slot for the calling thread. 
     * We have to find an empty slot.
     */
    if (!empty) {
        for (; i<lock->numEntries; i++) {
            RWEntry * entry = GET_ENTRY(lock,i);
            if (!entry->id) {
                empty = entry;
                break;
            }
        }

        /*
         * looks like we are out of luck. We need to reallocate the array
         * of thread entries.
         */
        if (!empty) {
            int count = lock->numEntries + STATIC_ENTRIES;
            size_t size = count * sizeof(RWEntry);
            RWEntry * newEntries = (RWEntry*)
                MEM_Realloc(lock->moreEntries, size);
            if (!newEntries) {
                return NULL;
            }
            
            lock->moreEntries = newEntries;
            lock->numEntries = count;
            empty = lock->moreEntries + i - STATIC_ENTRIES;
            memset(empty, 0, sizeof(RWEntry) * STATIC_ENTRIES);
        }

        lock->entriesInUse = i + 1;
    }

    lock->entriesActive++;

    /*
     * initialize the empty entry.
     */
    empty->id = self;
    empty->read = empty->write = 0L;

    return empty;
}
Beispiel #11
0
static gint prefs_actions_clist_set_row(gint row)
{
	const gchar *entry_text;
	gint len, action_nb;
	gchar action[PREFSBUFSIZE];
	gchar *new_action;

	GET_ENTRY(actions.name_entry);
	if (entry_text[0] == '\0') {
		alertpanel_error(_("Menu name is not set."));
		return -1;
	}

	if (entry_text[0] == '/') {
		alertpanel_error(_("A leading '/' is not allowed in the menu name."));
		return -1;
	}

	if (strchr(entry_text, ':')) {
		alertpanel_error(_("Colon ':' is not allowed in the menu name."));
		return -1;
	}

	action_nb = prefs_actions_find_by_name(entry_text);
	if ((action_nb != -1) && ((row == -1) || (row != action_nb + 1))) {
		alertpanel_error(_("There is an action with this name already."));
		return -1;
	}
	
	strncpy(action, entry_text, PREFSBUFSIZE - 1);

	while (strstr(action, "//")) {
		char *to_move = strstr(action, "//")+1;
		char *where = strstr(action, "//");
		int old_len = strlen(action);
		memmove(where, to_move, strlen(to_move));
		action[old_len-1] = '\0';
	}
	
	g_strstrip(action);

	/* Keep space for the ': ' delimiter */
	len = strlen(action) + 2;
	if (len >= PREFSBUFSIZE - 1) {
		alertpanel_error(_("Menu name is too long."));
		return -1;
	}

	strcat(action, ": ");

	GET_ENTRY(actions.cmd_entry);

	if (entry_text[0] == '\0') {
		alertpanel_error(_("Command-line not set."));
		return -1;
	}

	if (len + strlen(entry_text) >= PREFSBUFSIZE - 1) {
		alertpanel_error(_("Menu name and command are too long."));
		return -1;
	}

	if (action_get_type(entry_text) == ACTION_ERROR) {
		gchar *message;
		message = g_markup_printf_escaped(_("The command\n%s\nhas a syntax error."),
						entry_text);
		alertpanel_error("%s", message);
		g_free(message);
		return -1;
	}

	strcat(action, entry_text);

	new_action = g_strdup(action);	
	prefs_actions_list_view_insert_action(actions.actions_list_view,
	                                      row, new_action, TRUE);
						
	prefs_actions_set_list();

	return 0;
}
Beispiel #12
0
 
 if (param)
    {
    if (param == U_DPAGE_INIT) { usp_init_wi_auth(); return; }
 
    if (param == U_DPAGE_DESTROY) { usp_end_wi_auth(); return; }
 
    if (param == U_DPAGE_SIGHUP) { usp_sighup_wi_auth(); return; }
 
    if (param >= U_DPAGE_FORK) return;
    }
 
 U_http_info.endHeader = 0;
 
 static UHTTP::service_info GET_table[] = { // NB: the table must be ordered alphabetically for binary search...
    GET_ENTRY(admin),
    GET_ENTRY(admin_edit_ap),
    GET_ENTRY(admin_export_statistics_login_as_csv),
    GET_ENTRY(admin_export_statistics_registration_as_csv),
    GET_ENTRY(admin_export_view_using_historical_as_csv),
    GET_ENTRY(admin_historical_statistics_login),
    GET_ENTRY(admin_login_nodog),
    GET_ENTRY(admin_login_nodog_historical),
    GET_ENTRY(admin_login_nodog_historical_view_data),
    GET_ENTRY(admin_printlog),
    GET_ENTRY(admin_recovery),
    GET_ENTRY(admin_status_network),
    GET_ENTRY(admin_status_nodog),
    GET_ENTRY(admin_status_nodog_and_user),
    GET_ENTRY(admin_status_nodog_and_user_as_csv),
    GET_ENTRY(admin_view_statistics_login),
Beispiel #13
0
/**
 * Release n recursively acquired locks.
 */
void RWLOCK_UnlockMany(RWLock * lock, int n) 
{
    if (n > 0) {
        RWEntry * entry;
        MUTEX_Lock(&lock->mutex);
        entry = RWLOCK_FindEntry(lock);

        /*
         * if we cannot find the entry, it means that current thread 
         * does not own the lock. It's a programming error. 
         */
        ASSERT(entry);
        if (entry) {
            lock->locks--;
            
            /* first release write locks */
            if (entry->write > 0) {
                if (entry->write >= n) {
                    entry->write -= n;
                    n = 0;
                } else {
                    n -= entry->write;
                    entry->write = 0;
                }
            }

            /* then read locks */
            if (n > 0) {
                entry->read -= n;
            }

            /* 
             * ASSERT that current thread does not release more locks than 
             * it has acquired
             */
            ASSERT(lock->locks >= 0);
            ASSERT(entry->read >= 0);
            ASSERT(entry->write >= 0);

            /*
             * no more work to do unless calling thread has released the
             * resource (i.e. usage count came down to zero)
             */
            if ((entry->read + entry->write) <= 0) {
                int i;
                int inUse;
                QEntry * e;
                RWLockWaiter * shareWaiter = NULL;
                RWLockWaiter * exclusiveWaiter = NULL;

                entry->id = 0;

                lock->entriesActive--;
                ASSERT(lock->entriesActive >= 0);

                /* 
                 * update lock->entriesInUse
                 * NOTE that RWLOCK_FindStaticEntry() may access it without 
                 * synchronization.
                 */
                i = lock->entriesInUse - 1;
                inUse = 0;
                while (i >= 0) {
                    RWEntry * lockEntry = GET_ENTRY(lock,i);
                    if (lockEntry->id) {
                        inUse = i + 1;
                        break;
                    }
                    i--;
                }

                lock->entriesInUse = inUse;

                /*
                 * if resource was acquired exclusively, it must be free now
                 */
                if (lock->flags & RWLOCK_FLAG_EXCLUSIVE_LOCK) {
                    ASSERT(!lock->locks);
                    lock->flags &= ~RWLOCK_FLAG_EXCLUSIVE_LOCK;
                }

                /* 
                 * release the waiters in the order they have arrived
                 */
                e = QUEUE_First(&lock->shareWaiters);
                if (e) shareWaiter = QCAST(e,RWLockWaiter,entry);
                e = QUEUE_First(&lock->exclusiveWaiters);
                if (e) exclusiveWaiter = QCAST(e,RWLockWaiter,entry);

                if (exclusiveWaiter && (!shareWaiter ||
                    exclusiveWaiter->index < shareWaiter->index)) {
                    EVENT_Set(exclusiveWaiter->event);
                } else if (shareWaiter) {
                    /* this should unblock all shared waiters */
                    EVENT_Set(shareWaiter->event);
                }

            } else if (lock->flags & RWLOCK_FLAG_EXCLUSIVE_LOCK) {

                /*
                 * if the owner of the lock has released all its WRITE locks 
                 * but still have some READ locks, switch to shared mode.
                 */
                if (!entry->write) {            
                    QEntry * e;
                    RWLockWaiter * shareWaiter = NULL;
                    RWLockWaiter * exclusiveWaiter = NULL;

                    ASSERT(entry->read > 0);
                    lock->flags &= ~RWLOCK_FLAG_EXCLUSIVE_LOCK;

                    /*
                     * wake up shared waiters only unless the exclusive
                     * waiter is first in the line
                     */
                    e = QUEUE_First(&lock->shareWaiters);
                    if (e) shareWaiter = QCAST(e,RWLockWaiter,entry);
                    e = QUEUE_First(&lock->exclusiveWaiters);
                    if (e) exclusiveWaiter = QCAST(e,RWLockWaiter,entry);

                    if (shareWaiter && (!exclusiveWaiter ||
                        shareWaiter->index < exclusiveWaiter->index)) {
                        EVENT_Set(shareWaiter->event);
                    }
                }
            }
        }
        MUTEX_Unlock(&lock->mutex);
    }
}
Beispiel #14
0
void
PerformRender(renderlist_t *RenderList, gamestate_t *GameState)
{
    drawbuffer_t *DrawBuffer = &GameState->DrawBuffer;
    uint BufferSize = DrawBuffer->Width * DrawBuffer->Height;
    u8 *Pixels  = (u8 *)(DrawBuffer->Buffer);
    u8 *Address = (u8 *)RenderList->Data;
    
    bool FirstRender = false;

    for (renderop_e RenderOp = (renderop_e)*Address;
         RenderOp != RenderOp_stop;
         RenderOp = (renderop_e)*Address)
    {
        // Skip past render op
        Address += sizeof(renderop_e);

#define RENDERDATA(SubType)    (renderdata_##SubType##_t *)Address; Address += sizeof(renderdata_##SubType##_t)

        switch (RenderOp) {
            case RenderOp_clear:
            {
                uint Color = *(uint *)Address;
                Address += sizeof(uint);
                uint *Dst = (uint *)Pixels;
                for (uint i=0; i < BufferSize; ++i) {
                    *Dst++ = Color;
                }
                FirstRender = true; // Why? Because everything's gone now
                break;
            }

            case RenderOp_bitmap:
            {
                renderdata_bitmap_t *Bitmap = RENDERDATA(bitmap);
                artfile_entry_t *Entry = GET_ENTRY((&ArtsMemory), Bitmap->Id);
                u8 *EntryData = GET_ENTRY_DATA((&ArtsMemory), Bitmap->Id);
                int StartX = Bitmap->X * DrawBuffer->Width;
                int StartY = Bitmap->Y * DrawBuffer->Height;
                bool UseColorKey = Bitmap->Flags & BitmapFlag_ColorKey; 
                bool UseAlpha = Bitmap->Flags & BitmapFlag_Alpha;

                if (Bitmap->Flags & BitmapFlag_AlignLeft) {
                    StartX = 0;
                } else if (Bitmap->Flags & BitmapFlag_AlignRight) {
                    StartX = DrawBuffer->Width - Entry->Dim.Width * Bitmap->Width;
                }
                if (Bitmap->Flags & BitmapFlag_AlignTop) {
                    StartY = 0;
                } else if (Bitmap->Flags & BitmapFlag_AlignBottom) {
                    StartY = DrawBuffer->Height - Entry->Dim.Height * Bitmap->Height;
                }

                /*
                if (((StartX + Entry->Dim.Width < 0) && (StartY + Entry->Dim.Height < 0)) ||
                     (StartX > DrawBuffer->Width) && (StartY > DrawBuffer->Height))
                {
                    // Not visible
                    break;
                }
                */

                Bitmap->Width = (Bitmap->Width < 0 ? 0 : Bitmap->Width);
                Bitmap->Height = (Bitmap->Height < 0 ? 0 : Bitmap->Height);

                uint RealDimWidth = Entry->Dim.Width;
                uint RealDimHeight = Entry->Dim.Height;

                u8 *Src = EntryData;
                if (StartY < 0) {
                    Src += abs(StartY) * Entry->Dim.Width;
                    RealDimHeight -= abs(StartY);
                    StartY = 0;
                }
                if (StartX < 0) {
                    Src += abs(StartX);
                    RealDimWidth -= abs(StartX);
                    StartX = 0;
                }

                if (StartX + RealDimWidth > DrawBuffer->Width) {
                    RealDimWidth -= (StartX + RealDimWidth) - DrawBuffer->Width;
                }
                if (StartY + RealDimHeight > DrawBuffer->Height) {
                    RealDimHeight -= (StartY + RealDimHeight) - DrawBuffer->Height;
                }

                uint *Dst = (uint *)(Pixels + 4 * (StartY * DrawBuffer->Width + StartX));
                // uint *LastDst = (uint *)(Pixels + 4 * DrawBuffer->Width * DrawBuffer->Height - 1);
                float StepX = 1 / Bitmap->Width;
                float StepY = 1 / Bitmap->Height;

                uint DrawBufferSize = 4 * DrawBuffer->Width * DrawBuffer->Height - 1;

                for (float Y = 0; Y < Entry->Dim.Height; Y += StepY) {
                    if (((uint)(Y+0.5f)) >= RealDimHeight || !BoundsCheck(Pixels, DrawBufferSize, Dst) /*Dst > LastDst*/) {
                        break;
                    }
                    uint iY = (uint)Y;
                    uint Scanline = 0;
                    for (float X = 0; X < Entry->Dim.Width; X += StepX) {
                        //if (Dst > LastDst) {
                        if (Scanline >= DrawBuffer->Width ||
                            !BoundsCheck(Pixels, DrawBufferSize, Dst))
                        {
                            break;
                        }
                        uint iX = (uint)X;
                        u8 C = *(Src + iY * Entry->Dim.Width + iX);
                        uint FinalColor = 0; 
                        if (C) {
                            FinalColor = Bitmap->Color;
                        }
                        if (X < RealDimWidth &&
                            (!UseColorKey || FinalColor))
                        {
                            if (!FirstRender && UseAlpha) {
                                uint DstRaw = *Dst;
                                color_t DstColor = UintToColor(DstRaw);
                                color_t SrcColor = UintToColor(FinalColor);
                                float OneMinusSrcA = 1.0f - SrcColor.A;
                                DstColor.R = SrcColor.R + (DstColor.R * OneMinusSrcA);
                                DstColor.G = SrcColor.G + (DstColor.G * OneMinusSrcA);
                                DstColor.B = SrcColor.B + (DstColor.B * OneMinusSrcA);
                                FinalColor = ColorToRGB(DstColor);
                            }
                            *Dst = FinalColor;
                        }
                        ++Dst;
                        ++Scanline;
                    }
                    Dst += DrawBuffer->Width - Scanline; 
                }
                FirstRender = false;
                break;
            }

            default:
                assert(!"Unknown render op");
        }

#undef RENDERDATA

    }
}
Beispiel #15
0
// Deletes the minimum entry in the heap
int heap_delmin(heap* h, void** key, void** value) {
    // Check there is a minimum
    if (h->active_entries == 0)
        return 0;

    // Load in the map table
    void** map_table = h->mapping_table;

    // Get the root element
    int current_index = 0;
    heap_entry* current = GET_ENTRY(current_index, map_table);

    // Store the outputs
    if (key != NULL && value != NULL) {
        *key = current->key;
        *value = current->value;
    }

    // Reduce the number of active entries
    h->active_entries--;

    // Get the active entries
    int entries = h->active_entries;
   
    // If there are any other nodes, we may need to move them up
    if (h->active_entries > 0) {
        // Move the last element to the root
        heap_entry* last = GET_ENTRY(entries,map_table);
        current->key = last->key;
        current->value = last->value;

        // Loop variables
        heap_entry* left_child;
        heap_entry* right_child;

        // Load the comparison function
        int (*cmp_func)(void*,void*) = h->compare_func;

        // Store the left index
        int left_child_index;

        while (left_child_index = LEFT_CHILD(current_index), left_child_index < entries) {
            // Load the left child
            left_child = GET_ENTRY(left_child_index, map_table);

            // We have a left + right child
            if (left_child_index+1 < entries) {
                // Load the right child
                right_child = GET_ENTRY((left_child_index+1), map_table);

                // Find the smaller child
                if (cmp_func(left_child->key, right_child->key) <= 0) {

                    // Swap with the left if it is smaller
                    if (cmp_func(current->key, left_child->key) == 1) {
                        SWAP_ENTRIES(current,left_child);
                        current_index = left_child_index;
                        current = left_child;

                    // Otherwise, the current is smaller
                    } else
                        break;

                // Right child is smaller
                } else {

                    // Swap with the right if it is smaller
                    if (cmp_func(current->key, right_child->key) == 1) {
                        SWAP_ENTRIES(current,right_child);
                        current_index = left_child_index+1;
                        current = right_child;

                    // Current is smaller
                    } else
                        break;

                }


            // We only have a left child, only do something if the left is smaller
            } else if (cmp_func(current->key, left_child->key) == 1) {
                SWAP_ENTRIES(current,left_child);
                current_index = left_child_index;
                current = left_child;

            // Done otherwise
            }  else
                break;

        }
    } 

    // Check if we should release a page of memory
    int used_pages = entries / ENTRIES_PER_PAGE + ((entries % ENTRIES_PER_PAGE > 0) ? 1 : 0);

    // Allow one empty page, but not two
    if (h->allocated_pages > used_pages + 1 && h->allocated_pages > h->minimum_pages) {
        // Get the address of the page to delete
        void* addr = *(map_table+h->allocated_pages-1);

        // Map out
        map_out_pages(addr, 1);

        // Decrement the allocated count
        h->allocated_pages--;
    }

    // Success
    return 1;
}
Beispiel #16
0
// Insert a new element
void heap_insert(heap *h, void* key, void* value) {
    // Check if this heap is not destoyed
    assert(h->mapping_table != NULL);

    // Check if we have room
    int max_entries = h->allocated_pages * ENTRIES_PER_PAGE;
    if (h->active_entries + 1 > max_entries) {
        // Get the number of map pages
        int map_pages = h->map_pages;

        // We need a new page, do we have room?
        int mapable_pages = map_pages * PAGE_SIZE / sizeof(void*);
    
        // Check if we need to grow the map table
        if (h->allocated_pages + 1 > mapable_pages) {
            // Allocate a new table, slightly bigger
            void *new_table = map_in_pages(map_pages + 1);

            // Get the old table
            void *old_table = (void*)h->mapping_table;

            // Copy the old entries to the new table
            memcpy(new_table, old_table, map_pages * PAGE_SIZE);

            // Delete the old table
            map_out_pages(old_table, map_pages);

            // Swap to the new table
            h->mapping_table = (void**)new_table;

            // Update the number of map pages
            h->map_pages = map_pages + 1;
        }

        // Allocate a new page
        void* addr = map_in_pages(1);

        // Add this to the map
        *(h->mapping_table+h->allocated_pages) = addr;

        // Update the number of allocated pages
        h->allocated_pages++;
    }

    // Store the comparison function
    int (*cmp_func)(void*,void*) = h->compare_func;

    // Store the map table address
    void** map_table = h->mapping_table;

    // Get the current index
    int current_index = h->active_entries;
    heap_entry* current = GET_ENTRY(current_index, map_table);

    // Loop variables
    int parent_index;
    heap_entry *parent;

    // While we can, keep swapping with our parent
    while (current_index > 0) {
        // Get the parent index
        parent_index = PARENT_ENTRY(current_index);

        // Get the parent entry
        parent = GET_ENTRY(parent_index, map_table);
       
        // Compare the keys, and swap if we need to 
        if (cmp_func(key, parent->key) < 0) {
            // Move the parent down
            current->key = parent->key;
            current->value = parent->value;

            // Move our reference
            current_index = parent_index;
            current = parent;

        // We are done swapping
        }   else
            break;
    }

    // Insert at the current index
    current->key = key;
    current->value = value; 

    // Increase the number of active entries
    h->active_entries++;
}
Beispiel #17
0
static void cgen_expression(pSymbol func, pNode expr)
{
    switch (GET_TYPE(expr))
    {
    case EXPRESSION:
    {
        // Function call
        if (!GET_DATA(expr))
        {
            puts("\t# Function call");
            pNode iden = GET_CHILD(expr, 0), args = GET_CHILD(expr, 1);
            for (size_t i = 0; i < GET_SIZE(args); i++)
            {
                printf("\t# Arg num %zu\n", i);
                pNode arg = GET_CHILD(args, i);
                cgen_expression(func, arg);
                ASM1(pushq, %rax);
            }

            for (size_t i = 1; i <= GET_SIZE(args); i++)
                FASM1(popq, %s, record[GET_SIZE(args) - i]);
            FASM1(call, _%s, GET_ENTRY(iden)->name);
            puts("");
            return;
        }

        puts("\t# Expression evaluation");

        // Unary minus
        if (GET_SIZE(expr) == 1)
        {
            puts("\t# Unary minus");
            pNode ch = GET_CHILD(expr, 0);
            ADDR(movq, cgen_resaddr(func, GET_ENTRY(ch)), %rax);
            ASM1(negq, %rax);
            return;
        }

        // Normal operator epxression
        pNode ch0 = GET_CHILD(expr, 0), ch1 = GET_CHILD(expr, 1);

        // Left hand side
        cgen_expression(func, ch0);
        ASM1(pushq, %rax);

        // Right hand side
        cgen_expression(func, ch1);

        ASM1(popq, %r8);

        switch (*(char *)GET_DATA(expr))
        {
        case '+':
            puts("\t# Addition");
            ASM2(addq, %r8, %rax);
            break;
        case '-':
            puts("\t# Subtraction");
            ASM2(subq, %rax, %r8);
            ASM2(movq, %r8, %rax);
            break;
        case '*':
            puts("\t# Multiplication");
            ASM0(cqo);
            ASM1(imulq, %r8);
            break;
        case '/':
            puts("\t# Divition");
            ASM2(xchg, %rax, %r8);
            ASM0(cqo);
            ASM1(idivq, %r8);
            break;
        }
        puts("");
        break;
    }