Changeset 445 for trunk/libs/libalmosmkh


Ignore:
Timestamp:
May 29, 2018, 9:27:23 AM (7 years ago)
Author:
alain
Message:

Restructure the mini_libc.

Location:
trunk/libs/libalmosmkh
Files:
3 deleted
1 edited
2 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/libs/libalmosmkh/Makefile

    r444 r445  
    11############################################################################
    2 #                  Makefile for the ALMOS-MKH "mini-libc"                  #
     2#                  Makefile for the ALMOS-MKH specific library             #
    33############################################################################
    44
    55-include ../../params-soft.mk
     6
    67ifeq ($(ARCH_NAME),)
    78$(error Please define in ARCH_NAME parameter in params-soft.mk!)
    89endif
    910
    10 SRCS = almos-mkh.c almos-mkh-memory.c
     11SRCS = almosmkh.c
    1112
    1213OBJS = $(addprefix build/, $(SRCS:.c=.o)) \
    1314       $(HAL_ARCH)/build/core/hal_user.o
    1415
    15 INCLUDES = -I. -I$(HAL)/generic -I$(LIBC_INCLUDE) -I$(SHARED_INCLUDE) -I$(LIBPTHREAD_INCLUDE)
     16INCLUDES = -I.                     \
     17           -I$(LIBC_PATH)          \
     18           -I$(LIBPTHREAD_PATH)    \
     19           -I$(SHARED_INCLUDE)     \
     20           -I$(HAL)/generic        \
     21           -I$(HAL_ARCH)/core      \
     22           -I$(KERNEL)
    1623
    17 libs : build/lib/libalmos-mkh.a build/include/almos-mkh.h
     24libs : build/lib/libalmosmkh.a  headers
    1825
    1926build :
     
    2532        $(MAKE) -C $(HAL_ARCH)
    2633
    27 
    28 build/%.o : %.c
     34build/%.o : %.c %.h
    2935        $(CC) $(INCLUDES) $(CFLAGS) -c -o  $@ $<
    3036        $(DU) -D $@ > $@.txt
    3137
    3238headers: build
    33         cp almos-mkh.h build/include/.
    34 build/lib/libalmos-mkh.a: build $(OBJS)
     39        cp $(SRCS:.c=.h)  build/include/.
     40
     41build/lib/libalmosmkh.a: build  $(OBJS)
    3542        $(AR) rc $@ $(OBJS)
    36         ranlib $@
     43        $(RANLIB) $@
    3744
    38 .PHONY = build clean
    39 
     45.PHONY = build clean headers
    4046
    4147clean:
  • trunk/libs/libalmosmkh/almosmkh.c

    r444 r445  
     1/*
     2 * almosmkh.c - User level ALMOS-MKH specific library implementation.
     3 *
     4 * Author     Alain Greiner (2016,2017,2018)
     5 *
     6 * Copyright (c) UPMC Sorbonne Universites
     7 *
     8 * This file is part of ALMOS-MKH.
     9 *
     10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
     11 * under the terms of the GNU General Public License as published by
     12 * the Free Software Foundation; version 2.0 of the License.
     13 *
     14 * ALMOS-MKH is distributed in the hope that it will be useful, but
     15 * WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17 * General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU General Public License
     20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
     21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     22 */
     23
     24#include <almosmkh.h>
    125#include <hal_user.h>
    2 #include <almos-mkh.h>
     26#include <hal_types.h>
     27#include <syscalls_numbers.h>
     28#include <string.h>
    329#include <stdio.h>
    4 #include <syscalls_numbers.h>
    5 
    6 
    7 #define  reg_t     int
    8 
    9 /////////////     Non standard system calls ////////////////////////////////////
    10 
     30#include <stdlib.h>
     31#include <unistd.h>
     32#include <mman.h>
     33
     34/////////////     Non standard system calls    /////////////////////////////////
    1135
    1236//////////////////////////
     
    3761}
    3862
    39 ////////////////////////////////////
    40 void display_string( char * string )
    41 {
    42     hal_user_syscall( SYS_DISPLAY,
    43                       DISPLAY_STRING,
    44                       (reg_t)string, 0, 0 );
    45 }
    46 
    47 ///////////////////////////////////
    48 int display_vmm( unsigned int cxy, unsigned int pid )
    49 {
    50     return hal_user_syscall( SYS_DISPLAY,
    51                              DISPLAY_VMM,
    52                              (reg_t)pid,
    53                              (reg_t)cxy, 0 );
    54 }
    55 
    56 ////////////////////////////////
    57 int display_sched( unsigned int cxy,
    58                    unsigned int lid )
    59 {
    60     return hal_user_syscall( SYS_DISPLAY,
    61                              DISPLAY_SCHED,
    62                              (reg_t)cxy,
    63                              (reg_t)lid, 0 );
    64 }
    65 
    66 /////////////////////////////////////////////////
    67 int display_cluster_processes( unsigned int cxy )
    68 {
    69     return hal_user_syscall( SYS_DISPLAY,
    70                              DISPLAY_CLUSTER_PROCESSES,
    71                              (reg_t)cxy, 0, 0 );
    72 }
    73 
    74 ///////////////////
    75 int display_chdev()
    76 {
    77     return hal_user_syscall( SYS_DISPLAY,
    78                              DISPLAY_CHDEV, 0, 0, 0 );
    79 }
    80 
    81 /////////////////
    82 int display_vfs()
    83 {
    84     return hal_user_syscall( SYS_DISPLAY,
    85                              DISPLAY_VFS, 0, 0, 0 );
    86 }
    87 
    88 ////////////////////////////////////////////////
    89 int display_txt_processes( unsigned int txt_id )
    90 {
    91     return hal_user_syscall( SYS_DISPLAY,
    92                              DISPLAY_TXT_PROCESSES,
    93                              (reg_t)txt_id, 0, 0 );
    94 }
    95 
    9663///////////////////////////////////////////
    9764int get_cycle( unsigned long long * cycle )
     
    9966    return hal_user_syscall( SYS_GET_CYCLE,
    10067                             (reg_t)cycle, 0, 0, 0 );
    101 }
    102 
    103 //////////////////////////////////
    104 int trace( unsigned int active,
    105            unsigned int pid,
    106            unsigned int lid )
    107 {
    108     return hal_user_syscall( SYS_TRACE,
    109                              (reg_t)active,
    110                              (reg_t)pid,
    111                              (reg_t)lid, 0 );
    11268}
    11369
     
    12076                             (reg_t)value, 0, 0 );
    12177}
    122 
    12378
    12479////////////
     
    207162}  // end getint()
    208163
     164
     165///////////////    non standard debug functions    //////////////////////////
     166
     167////////////////////////////////////
     168void display_string( char * string )
     169{
     170    hal_user_syscall( SYS_DISPLAY,
     171                      DISPLAY_STRING,
     172                      (reg_t)string, 0, 0 );
     173}
     174
     175///////////////////////////////////
     176int display_vmm( unsigned int cxy, unsigned int pid )
     177{
     178    return hal_user_syscall( SYS_DISPLAY,
     179                             DISPLAY_VMM,
     180                             (reg_t)pid,
     181                             (reg_t)cxy, 0 );
     182}
     183
     184////////////////////////////////
     185int display_sched( unsigned int cxy,
     186                   unsigned int lid )
     187{
     188    return hal_user_syscall( SYS_DISPLAY,
     189                             DISPLAY_SCHED,
     190                             (reg_t)cxy,
     191                             (reg_t)lid, 0 );
     192}
     193
     194/////////////////////////////////////////////////
     195int display_cluster_processes( unsigned int cxy )
     196{
     197    return hal_user_syscall( SYS_DISPLAY,
     198                             DISPLAY_CLUSTER_PROCESSES,
     199                             (reg_t)cxy, 0, 0 );
     200}
     201
     202///////////////////
     203int display_chdev()
     204{
     205    return hal_user_syscall( SYS_DISPLAY,
     206                             DISPLAY_CHDEV, 0, 0, 0 );
     207}
     208
     209/////////////////
     210int display_vfs()
     211{
     212    return hal_user_syscall( SYS_DISPLAY,
     213                             DISPLAY_VFS, 0, 0, 0 );
     214}
     215
     216////////////////////////////////////////////////
     217int display_txt_processes( unsigned int txt_id )
     218{
     219    return hal_user_syscall( SYS_DISPLAY,
     220                             DISPLAY_TXT_PROCESSES,
     221                             (reg_t)txt_id, 0, 0 );
     222}
     223
     224//////////////////////////////////
     225int trace( unsigned int active,
     226           unsigned int pid,
     227           unsigned int lid )
     228{
     229    return hal_user_syscall( SYS_TRACE,
     230                             (reg_t)active,
     231                             (reg_t)pid,
     232                             (reg_t)lid, 0 );
     233}
     234
     235//////////////////
     236int display_dqdt()
     237{
     238    return hal_user_syscall( SYS_DISPLAY,
     239                             DISPLAY_DQDT, 0, 0, 0 );
     240}
     241
    209242///////////
    210243void idbg()
     
    283316
    284317
    285 
     318///////////////    non standard debug functions    //////////////////////////
     319
     320#define  MALLOC_DEBUG  0
     321 
     322/////////////////////////////////////////////////////////////////////////////////////////
     323// Global variable defining the allocator array (one per cluster)
     324// This array (about 16 Kbytes ) will be stored in the data segment
     325// of any application linked with this malloc libray.
     326/////////////////////////////////////////////////////////////////////////////////////////
     327
     328malloc_store_t   store[MALLOC_MAX_CLUSTERS];
     329
     330// Macro returning the smallest power of 2 larger or equal to size value
     331
     332#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
     333                                            (size <= 0x00000002) ? 1  :\
     334                                            (size <= 0x00000004) ? 2  :\
     335                                            (size <= 0x00000008) ? 3  :\
     336                                            (size <= 0x00000010) ? 4  :\
     337                                            (size <= 0x00000020) ? 5  :\
     338                                            (size <= 0x00000040) ? 6  :\
     339                                            (size <= 0x00000080) ? 7  :\
     340                                            (size <= 0x00000100) ? 8  :\
     341                                            (size <= 0x00000200) ? 9  :\
     342                                            (size <= 0x00000400) ? 10 :\
     343                                            (size <= 0x00000800) ? 11 :\
     344                                            (size <= 0x00001000) ? 12 :\
     345                                            (size <= 0x00002000) ? 13 :\
     346                                            (size <= 0x00004000) ? 14 :\
     347                                            (size <= 0x00008000) ? 15 :\
     348                                            (size <= 0x00010000) ? 16 :\
     349                                            (size <= 0x00020000) ? 17 :\
     350                                            (size <= 0x00040000) ? 18 :\
     351                                            (size <= 0x00080000) ? 19 :\
     352                                            (size <= 0x00100000) ? 20 :\
     353                                            (size <= 0x00200000) ? 21 :\
     354                                            (size <= 0x00400000) ? 22 :\
     355                                            (size <= 0x00800000) ? 23 :\
     356                                            (size <= 0x01000000) ? 24 :\
     357                                            (size <= 0x02000000) ? 25 :\
     358                                            (size <= 0x04000000) ? 26 :\
     359                                            (size <= 0x08000000) ? 27 :\
     360                                            (size <= 0x10000000) ? 28 :\
     361                                            (size <= 0x20000000) ? 29 :\
     362                                            (size <= 0x40000000) ? 30 :\
     363                                            (size <= 0x80000000) ? 31 :\
     364                                                                   32
     365
     366////////////////////////////////////////////////////////////////////////////////////////////
     367// This static function display the current state of the allocator in cluster <cxy>.
     368////////////////////////////////////////////////////////////////////////////////////////////
     369
     370#if 0
     371static void display_free_array( unsigned int cxy )
     372{
     373    unsigned int next;
     374    unsigned int id;
     375    unsigned int iter;
     376
     377    printf("\n*****   store[%x] base = %x / size = %x\n",
     378    cxy , store[cxy].store_base, store[cxy].store_size );
     379    for ( id = 0 ; id < 32 ; id++ )
     380    {
     381        next = store[cxy].free[id];
     382        printf(" - free[%d] = " , id );
     383        iter = 0;
     384        while ( next != 0 )
     385        {
     386            printf("%x | ", next );
     387            next = (*(unsigned int*)next);
     388            iter++;
     389        }
     390        printf("0\n");
     391    }
     392}  // end display_free_array()
     393#endif
     394
     395
     396////////////////////////////////////////////////////////////////////i//////////////////////
     397// This static function initialises the store in the cluster identified by the <cxy>
     398// arguments. It is called by the malloc() or remote_malloc when a specific store(x,y)
     399// is accessed for the first time by a remote() or remote_malloc() request.
     400// It uses the mmap( MAP_REMOTE ) syscall to allocate a new vseg mapped in cluster (cxy).
     401////////////////////////////////////////////////////////////////////i//////////////////////
     402// @ cxy        : target cluster identifier (fixed format).
     403// @ store_size : store size (bytes).
     404// # return without setting the initialized field in store(cxy) if failure.
     405////////////////////////////////////////////////////////////////////i//////////////////////
     406static void store_init( unsigned int cxy,
     407                        unsigned int store_size )
     408{
     409    unsigned int   store_base;       // store base address
     410    unsigned int   free_index;       // index in free[array]
     411
     412    unsigned int   alloc_base;       // alloc[] array base
     413    unsigned int   alloc_size;       // alloc[] array size
     414    unsigned int   alloc_index;      // index in alloc[array]
     415
     416    unsigned int   iter;             // iterator
     417
     418#if MALLOC_DEBUG
     419printf("\n[MALLOC] %s : enter for store[%x] / size = %x\n",
     420__FUNCTION__, cxy, store_size );
     421#endif
     422
     423    // get index in free[] array from size
     424    free_index = GET_SIZE_INDEX( store_size );
     425
     426    // check store size power of 2
     427    if( store_size != (1<<free_index) )
     428    {
     429        printf("\n[ERROR] in %s : store[%x] size not power of 2 / size = %x\n",
     430        __FUNCTION__, cxy , store_size );
     431        return;
     432    }
     433
     434    // allocate store in virtual space
     435    void * vadr = mmap( NULL,                     // MAP_FIXED not supported
     436                        store_size,
     437                        PROT_READ | PROT_WRITE,
     438                        MAP_REMOTE| MAP_SHARED,
     439                        cxy,                      // fd is cluster identifier
     440                        0 );                      // offset unused
     441
     442    if( vadr == NULL )
     443    {
     444        printf("\n[ERROR] in %s : cannot mmap store[%x]\n",
     445        __FUNCTION__, cxy );
     446        return;
     447    }
     448
     449    store_base = (unsigned int)vadr;
     450
     451    // check allocated store alignment
     452    if( store_base % store_size )
     453    {
     454        printf("\n[ERROR] in %s : store[%x] not aligned / base = %x / size = %x\n",
     455        __FUNCTION__, cxy , store_base , store_size );
     456        return;
     457    }
     458
     459#if MALLOC_DEBUG
     460printf("\n[MALLOC] %s : mmap done for store[%x] / base = %x\n",
     461__FUNCTION__, cxy, store_base );
     462#endif
     463
     464    // compute size of block containing alloc[] array
     465    alloc_size = store_size / MALLOC_MIN_BLOCK_SIZE;
     466    if ( alloc_size < MALLOC_MIN_BLOCK_SIZE) alloc_size = MALLOC_MIN_BLOCK_SIZE;
     467
     468    // get index for the corresponding block
     469    alloc_index = GET_SIZE_INDEX( alloc_size );
     470
     471    // compute alloc[] array base address
     472    alloc_base = store_base + store_size - alloc_size;
     473
     474    // reset the free[] array
     475    for ( iter = 0 ; iter < 32 ; iter++ )
     476    {
     477        store[cxy].free[iter] = 0;
     478    }
     479
     480    // DEPRECATED: we don't reset the alloc_size array
     481    // because we don't want to allocate the physical memory
     482    // when the heap is created  [AG]
     483    // memset( (void *)alloc_base , 0 , alloc_size );
     484 
     485    // split the store into various sizes blocks,
     486    // initializes the free[] array and NEXT pointers
     487    // base is the block base address
     488    unsigned int   base = store_base;
     489    unsigned int * ptr;
     490    for ( iter = free_index-1 ; iter >= alloc_index ; iter-- )
     491    {
     492        store[cxy].free[iter] = base;
     493        ptr = (unsigned int*)base;
     494        *ptr = 0;
     495        base = base + (1<<iter);
     496    }
     497
     498    // initialize store mutex
     499    if( pthread_mutex_init( &store[cxy].mutex , NULL ) )
     500    {
     501        printf("\n[ERROR] in %s : cannot initialize mutex for store[%x]\n",
     502        __FUNCTION__, cxy );
     503        return;
     504    }
     505
     506    store[cxy].cxy         = cxy;
     507    store[cxy].store_base  = store_base;
     508    store[cxy].store_size  = store_size;
     509    store[cxy].alloc_size  = alloc_size;
     510    store[cxy].alloc_base  = alloc_base;
     511    store[cxy].initialized = MALLOC_INITIALIZED;
     512
     513
     514#if MALLOC_DEBUG
     515printf("\n[MALLOC] %s : completes store[%x] initialisation\n",
     516__FUNCTION__, cxy );
     517
     518display_free_array( cxy );
     519#endif
     520
     521}  // end store_init()
     522
     523////////////////////////////////////////////////////////
     524static unsigned int split_block( malloc_store_t * store,
     525                                 unsigned int     vaddr,
     526                                 unsigned int     searched_index,
     527                                 unsigned int     requested_index )
     528{
     529    // push the upper half block into free[searched_index-1]
     530    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
     531    *new                         = store->free[searched_index-1];
     532    store->free[searched_index-1] = (unsigned int)new;
     533       
     534    if ( searched_index == requested_index + 1 )  // terminal case: return lower half block
     535    {
     536        return vaddr;
     537    }
     538    else            // non terminal case : lower half block must be split again
     539    {                               
     540        return split_block( store, vaddr, searched_index-1, requested_index );
     541    }
     542} // end split_block()
     543
     544//////////////////////////////////////////////////////
     545static unsigned int get_block( malloc_store_t * store,
     546                               unsigned int     searched_index,
     547                               unsigned int     requested_index )
     548{
     549    // test terminal case
     550    if ( (1<<searched_index) > store->store_size )  // failure : return a NULL value
     551    {
     552        return 0;
     553    }
     554    else                            // search a block in free[searched_index]
     555    {
     556        unsigned int vaddr = store->free[searched_index];
     557        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
     558        {
     559            return get_block( store, searched_index+1, requested_index );
     560        }
     561        else                // block found : pop it from free[searched_index]
     562        {
     563            // pop the block from free[searched_index]
     564            unsigned int next = *((unsigned int*)vaddr);
     565            store->free[searched_index] = next;
     566           
     567            // test if the block must be split
     568            if ( searched_index == requested_index )  // no split required
     569            {
     570                return vaddr;
     571            }
     572            else                                      // split is required
     573            {
     574                return split_block( store, vaddr, searched_index, requested_index );
     575            }
     576        }
     577    }
     578} // end get_block()
     579
     580////////////////////////////////////////
     581void * remote_malloc( unsigned int size,
     582                      unsigned int cxy )
     583{
     584
     585#if MALLOC_DEBUG
     586printf("\n[MALLOC] %s : enter for size = %x / cxy = %x\n",
     587__FUNCTION__ , size , cxy );
     588#endif
     589
     590    // check arguments
     591    if( size == 0 )
     592    {
     593        printf("\n[ERROR] in %s : requested size = 0 \n",
     594        __FUNCTION__ );
     595        return NULL;
     596    }
     597    if( cxy >= MALLOC_MAX_CLUSTERS )
     598    {
     599        printf("\n[ERROR] in %s : illegal cluster %x\n",
     600        __FUNCTION__ , cxy );
     601        return NULL;
     602    }
     603
     604    // initializes target store if required
     605    if( store[cxy].initialized != MALLOC_INITIALIZED )
     606    {
     607        store_init( cxy , MALLOC_LOCAL_STORE_SIZE );
     608
     609        if( store[cxy].initialized != MALLOC_INITIALIZED )
     610        {
     611            printf("\n[ERROR] in %s : cannot allocate store in cluster %x\n",
     612            __FUNCTION__ , cxy );
     613            return NULL;
     614        }
     615    }
     616
     617    // normalize size
     618    if ( size < MALLOC_MIN_BLOCK_SIZE ) size = MALLOC_MIN_BLOCK_SIZE;
     619
     620    // compute requested_index for the free[] array
     621    unsigned int requested_index = GET_SIZE_INDEX( size );
     622
     623    // take the lock protecting access to store[cxy]
     624    pthread_mutex_lock( &store[cxy].mutex );
     625
     626    // call the recursive function get_block
     627    unsigned int base = get_block( &store[cxy],
     628                                   requested_index,
     629                                   requested_index );
     630
     631    // check block found
     632    if (base == 0)
     633    {
     634        pthread_mutex_unlock( &store[cxy].mutex );
     635        printf("\n[ERROR] in %s : no more space in cluster %x\n",
     636        __FUNCTION__ , cxy );
     637        return NULL;
     638    }
     639
     640    // compute pointer in alloc[] array
     641    unsigned        offset = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
     642    unsigned char * ptr    = (unsigned char*)(store[cxy].alloc_base + offset);
     643
     644    // DEPRECATED : we don't check the alloc[] array,
     645    // because it has not been initialised, to avoid
     646    // physical memory allocation at heap creation [AG]
     647    // if ( *ptr != 0 )
     648    // {
     649    //    pthread_mutex_unlock( &store[cxy].mutex );
     650    //    printf("\n[PANIC] in %s : allocate an already allocated block...\n",
     651    //    __FUNCTION__ );
     652    //    return NULL;
     653    // }
     654
     655    // update alloc_array
     656    *ptr = requested_index;
     657
     658    // release the lock
     659    pthread_mutex_unlock( &store[cxy].mutex );
     660 
     661#if MALLOC_DEBUG
     662printf("\n[MALLOC] %s : exit / base = %x / size = %x / from store[%x]\n",
     663__FUNCTION__, base , size , cxy );
     664#endif
     665
     666    return (void*) base;
     667
     668} // end remote_malloc()
     669
     670
     671
     672//////////////////////////////////////////
     673void * remote_calloc ( unsigned int count,
     674                       unsigned int size,
     675                       unsigned int cxy )
     676{
     677    void * ptr = remote_malloc( count * size , cxy );
     678    memset( ptr , 0 , count * size );
     679    return ptr;
     680}
     681
     682//////////////////////////////////
     683void * remote_realloc( void * ptr,
     684                       unsigned int size,
     685                       unsigned int cxy )
     686{
     687    // simple allocation when (ptr == NULL)
     688    if( ptr == NULL )
     689    {
     690        return remote_malloc( size , cxy );
     691    }
     692
     693    // simple free when (size == 0)
     694    if( size == 0 )
     695    {
     696        remote_free( ptr , cxy );
     697        return NULL;
     698    }
     699
     700    // check cxy and ptr in general case
     701    if( cxy >= MALLOC_MAX_CLUSTERS )
     702    {
     703        printf("\n[ERROR] in %s : illegal cluster index %x\n",
     704        __FUNCTION__ , cxy );
     705        return NULL;
     706    }
     707
     708    unsigned int base = (unsigned int)ptr;
     709
     710    if( (base < store[cxy].store_base) ||
     711        (base >= (store[cxy].store_base + store[cxy].store_size)) )
     712    {
     713        printf("\n[ERROR] in %s : illegal pointer = %x\n",
     714        __FUNCTION__, ptr );
     715        return NULL;
     716    }
     717 
     718    // compute index in free[] array
     719    int index = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
     720
     721    // compute old size
     722    char * pchar = (char *) (store[cxy].alloc_base + index);
     723    int old_size = 1 << ((int) *pchar);
     724
     725    // allocate a new block
     726    void * new_ptr = remote_malloc( size , cxy );
     727
     728    // save old data to new block
     729    int min_size = (size < old_size) ? size : old_size;
     730    memcpy( new_ptr, ptr, min_size );
     731
     732    // release old block
     733    remote_free( ptr , cxy );
     734
     735    return new_ptr;
     736}
     737
     738//////////////////////////////////////////////////////
     739static void update_free_array( malloc_store_t * store,
     740                               unsigned int     base,
     741                               unsigned int     size_index )
     742{
     743    // This recursive function try to merge the released block
     744    // with the companion block if this companion block is free.
     745    // This companion has the same size, and almost the same address
     746    // (only one address bit is different)
     747    // - If the companion is not in free[size_index],
     748    //   the released block is pushed in free[size_index].
     749    // - If the companion is found, it is evicted from free[size_index]
     750    //   and the merged bloc is pushed in the free[size_index+1].
     751
     752
     753    // compute released block size
     754    unsigned int size = 1<<size_index;
     755
     756    // compute companion block and merged block base addresses
     757    unsigned int companion_base; 
     758    unsigned int merged_base; 
     759
     760    if ( (base & size) == 0 )   // the released block is aligned on (2*size)
     761    {
     762        companion_base  = base + size;
     763        merged_base     = base;
     764    }
     765    else
     766    {
     767        companion_base  = base - size;
     768        merged_base     = base - size;
     769    }
     770
     771    // scan all blocks in free[size_index]
     772    // the iter & prev variables are actually addresses
     773    unsigned int  found = 0;
     774    unsigned int  iter  = store->free[size_index];
     775    unsigned int  prev  = (unsigned int)&store->free[size_index];
     776    while ( iter )
     777    {
     778        if ( iter == companion_base )
     779        {
     780            found = 1;
     781            break;
     782        }
     783        prev = iter;
     784        iter = *(unsigned int*)iter;
     785    }
     786
     787    if ( found == 0 )  // Companion not found => push in free[size_index] 
     788    {
     789        *(unsigned int*)base   = store->free[size_index];
     790        store->free[size_index] = base;
     791    }
     792    else               // Companion found : merge
     793    {
     794        // evict the searched block from free[size_index]
     795        *(unsigned int*)prev = *(unsigned int*)iter;
     796
     797        // call the update_free() function for free[size_index+1]
     798        update_free_array( store, merged_base , size_index+1 );
     799    }
     800}  // end update_free_array()
     801
     802////////////////////////////////////
     803void remote_free( void        * ptr,
     804                  unsigned int  cxy )
     805{
     806
     807#if MALLOC_DEBUG
     808printf("\n[MALLOC] %s : enter for block = %x / cxy = %x\n",
     809__FUNCTION__, ptr, cxy );
     810#endif
     811
     812    unsigned int base = (unsigned int)ptr;
     813
     814    // check cxy value
     815    if( cxy >= MALLOC_MAX_CLUSTERS )
     816    {
     817        printf("\n[ERROR] in %s : illegal cluster index %x\n",
     818        __FUNCTION__ , cxy );
     819        return;
     820    }
     821
     822    // check ptr value
     823    if( (base < store[cxy].store_base) ||
     824        (base >= (store[cxy].store_base + store[cxy].store_size)) )
     825    {
     826        printf("\n[ERROR] in %s : illegal pointer for released block = %x\n",
     827        __FUNCTION__, ptr );
     828        return;
     829    }
     830 
     831    // get the lock protecting store[cxy]
     832    pthread_mutex_lock( &store[cxy].mutex );
     833
     834    // compute released block index in alloc[] array
     835    unsigned index = (base - store[cxy].store_base ) / MALLOC_MIN_BLOCK_SIZE;
     836 
     837    // get the released block size_index
     838    unsigned char* pchar      = (unsigned char*)(store[cxy].alloc_base + index);
     839    unsigned int   size_index = (unsigned int)*pchar;
     840
     841    // check block is allocated
     842    if ( size_index == 0 )
     843    {
     844        pthread_mutex_unlock( &store[cxy].mutex );
     845        printf("\n[ERROR] in %s : released block not allocated / ptr = %x\n",
     846        __FUNCTION__, ptr );
     847        return;
     848    }
     849
     850    // check released block alignment
     851    if ( base % (1 << size_index) )
     852    {
     853        pthread_mutex_unlock( &store[cxy].mutex );
     854        printf("\n[ERROR] in %s : released block not aligned / ptr = %x\n",
     855        __FUNCTION__, ptr );
     856        return;
     857    }
     858
     859    // reset the alloc[index] entry
     860    *pchar = 0;
     861
     862    // call the recursive function update_free_array()
     863    update_free_array( &store[cxy], base, size_index );
     864
     865    // release the lock
     866    pthread_mutex_unlock( &store[cxy].mutex );
     867
     868#if MALLOC_DEBUG
     869printf("\n[MALLOC] %s : conmpletes for block = %x / cxy = %x\n",
     870__FUNCTION__, ptr, cxy );
     871#endif
     872
     873} // end remote_free()
     874
     875// Local Variables:
     876// tab-width: 4
     877// c-basic-offset: 4
     878// c-file-offsets:((innamespace . 0)(inline-open . 0))
     879// indent-tabs-mode: nil
     880// End:
     881// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
     882
     883
     884
  • trunk/libs/libalmosmkh/almosmkh.h

    r444 r445  
     1/*
     2 * almosmkh.h - User level ALMOS-MKH specific library definition.
     3 *
     4 * Author     Alain Greiner (2016,2017,2018)
     5 *
     6 * Copyright (c) UPMC Sorbonne Universites
     7 *
     8 * This file is part of ALMOS-MKH.
     9 *
     10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
     11 * under the terms of the GNU General Public License as published by
     12 * the Free Software Foundation; version 2.0 of the License.
     13 *
     14 * ALMOS-MKH is distributed in the hope that it will be useful, but
     15 * WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17 * General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU General Public License
     20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
     21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     22 */
     23
    124#ifndef _LIBALMOSMKH_H_
    225#define _LIBALMOSMKH_H_
    326
    4 #include <almos-mkh/almos-mkh.h>
     27/***************************************************************************************
     28 * various the user level, ALMOS-MKH specific library. It contains:
     29 * - non standard system calls.
     30 * - debug functions.
     31 * - remote malloc extensions.
     32 **************************************************************************************/
     33
    534#include <pthread.h>
    6 
    7 /****************** Non standard (ALMOS_MKH specific) system calls **********************/
    8 
    9 
    10 /*****************************************************************************************
     35#include <shared_almos.h>
     36
     37/****************** Non standard (ALMOS_MKH specific) system calls ********************/
     38
     39
     40/***************************************************************************************
    1141 * This function is used to give the process identified by the <pid> argument the
    1242 * exclusive ownership of the attached TXT_RX terminal.
    13  *****************************************************************************************
     43 ***************************************************************************************
    1444 * @ pid        : process identifier.
    1545 * @ returns O if success / returns -1 if process not found.
    16  ****************************************************************************************/
     46 **************************************************************************************/
    1747int fg( unsigned int pid );
    1848
     
    4979
    5080/***************************************************************************************
     81 * This function implement the operations related to User Thread Local Storage.
     82 ***************************************************************************************
     83 * @ operation  : UTLS operation type as defined in "shared_sycalls.h" file.
     84 * @ value      : argument value for the UTLS_SET operation.
     85 * @ return value for the UTLS_GET and UTLS_GET_ERRNO / return -1 if failure.
     86 **************************************************************************************/
     87int utls( unsigned int operation,
     88          unsigned int value );
     89
     90/***************************************************************************************
     91 * This function returns a positive integer fom the standard "stdin" stream.
     92 ***************************************************************************************
     93 * returns the integer value if success / returns -1 if failure.
     94 **************************************************************************************/
     95int getint();
     96
     97
     98/***************** Non standard (ALMOS-MKH specific) debug functions ******************/
     99
     100
     101/***************************************************************************************
    51102 * This debug function displays on the kernel terminal TXT0
    52103 * the thread / process / core identifiers, the current cycle, plus a user defined
     
    91142/***************************************************************************************
    92143 * This debug function displays on the kernel terminal TXT0
     144 * the list of processes attached to a given TXT channel.
     145 * It can be called by any thread running in any cluster.
     146 ***************************************************************************************
     147 * @ txt_id   : [in] TXT terminal indes.
     148 * @ return 0 if success / return -1 if illegal argument.
     149 **************************************************************************************/
     150int display_txt_processes( unsigned int txt_id );
     151
     152/***************************************************************************************
     153 * This debug function displays on the kernel terminal TXT0
    93154 * the list of channel devices available in the architecture.
    94155 * It can be called by any thread running in any cluster.
     
    108169
    109170/***************************************************************************************
    110  * This debug function displays on the kernel terminal TXT0
    111  * the list of processes attached to a given TXT channel.
    112  * It can be called by any thread running in any cluster.
    113  ***************************************************************************************
    114  * @ return always 0.
    115  **************************************************************************************/
    116 int display_txt_processes( unsigned int txt_id );
     171 * This debug function displays on the kernel terminal TXT0 the current DQDT state.
     172 * It can be called by any thread running in any cluster.
     173 ***************************************************************************************
     174 * @ return always 0.
     175 **************************************************************************************/
     176int display_dqdt();
    117177
    118178/*****************************************************************************************
     
    126186* @ returns O if success / returns -1 if illegal arguments.
    127187****************************************************************************************/
    128 
    129188int trace( unsigned int active,
    130189           unsigned int pid,
    131190           unsigned int trdid );
    132191
    133 /*****************************************************************************************
    134  * This function implement the operations related to User Thread Local Storage.
    135  *****************************************************************************************
    136  * @ operation  : UTLS operation type as defined in "shared_sycalls.h" file.
    137  * @ value      : argument value for the UTLS_SET operation.
    138  * @ return value for the UTLS_GET and UTLS_GET_ERRNO / return -1 if failure.
    139  ****************************************************************************************/
    140 int utls( unsigned int operation,
    141           unsigned int value );
    142 
    143 /*********************************************************************************************
    144  * This function returns a positive integer fom the standard "stdin" stream.
    145  *********************************************************************************************
    146  * returns the integer value if success / returns -1 if failure.
    147  ********************************************************************************************/
    148 int getint();
    149 
    150 
    151 /////// Non-standard memory operations ////////////
    152 ////////////////////////////////////////////////////////////////////////////////
     192/****************************************************************************************
     193 * This blocking function implements an user-level interactive debugger that can be
     194 * introduced in any user application to display various kernel distributed structures.
     195 * The supported commands are:
     196 * - p (cxy)     : display all processes descriptors in a given cluster.
     197 * - s (cxy,lid) : display all threads attached to a given core in a given cluster.
     198 * - v (cxy)     : display the calling process VMM in a given cluster.
     199 * - t (tid)     : display all owner process descriptors attached to a TXT terminal.
     200 * - x           : force the calling process to exit.
     201 * - c           : continue calling process execution.
     202 * - h           : list the supported commands
     203 ***************************************************************************************/
     204void idbg();
     205
     206
     207/****************** Non standard (ALMOS-MKH specific) malloc operations  ***************/
     208
     209/////////////////////////////////////////////////////////////////////////////////////////
    153210// General principles:
    154211// - In user space the HEAP zone spread between the ELF zone and the STACK zone,
     
    168225//        We should introduce the possibility to dynamically allocate
    169226//        several vsegs in each cluster, using several mmap when required.
    170 ////////////////////////////////////////////////////////////////////////////////
     227/////////////////////////////////////////////////////////////////////////////////////////
    171228// Free blocks organisation in each cluster :
    172229// - All free blocks have a size that is a power of 2, larger or equal
     
    179236// - The pointers on the first free block for each size are stored in an
    180237//   array of pointers free[32] in the storage(x,y) descriptor.
    181 ////////////////////////////////////////////////////////////////////////////////
     238/////////////////////////////////////////////////////////////////////////////////////////
    182239// Allocation policy:
    183240// - The block size required by the user can be any value, but the allocated
     
    200257//   If the vseg is aligned (the vseg base is a multiple of the
    201258//   vseg size), all allocated blocks are aligned on the actual_size.
    202 ////////////////////////////////////////////////////////////////////////////////
     259/////////////////////////////////////////////////////////////////////////////////////////
    203260// Free policy:
    204261// - Each allocated block is registered in an alloc[] array of unsigned char.
     
    213270// - The alloc[] array is stored at the end of heap segment. This consume
    214271//   (1 / MALLOC_MIN_BLOCK_SIZE) of the total storage capacity.
    215 ////////////////////////////////////////////////////////////////////////////////
     272/////////////////////////////////////////////////////////////////////////////////////////
    216273
    217274
     
    221278#define MALLOC_MAX_CLUSTERS        0x100        // 256 clusters
    222279
    223 ////////////////////////////////////////////////////////////////////////////////
    224 // store(x,y) descriptor (one per cluster)
    225 ////////////////////////////////////////////////////////////////////////////////
     280/////////////////////////////////////////////////////////////////////////////////////////
     281//               store(x,y) descriptor (one per cluster)
     282/////////////////////////////////////////////////////////////////////////////////////////
    226283
    227284typedef struct malloc_store_s
    228285{
    229     pthread_mutex_t mutex;           // lock protecting exclusive access
     286    pthread_mutex_t mutex;           // lock protecting exclusive access to local heap
    230287    unsigned int    initialized;     // initialised when value == MALLOC_INITIALIZED
    231288    unsigned int    cxy;             // cluster identifier 
     
    276333                       unsigned int  size,
    277334                       unsigned int  cxy );
     335
    278336/*****************************************************************************************
    279337 * This function allocates enough space for <count> objects that are <size> bytes
     
    290348                      unsigned int cxy );
    291349
    292 /*********************************************************************************************
    293  * This blocking function implements an user-level interactive debugger that can be
    294  * introduced in any user application to display various kernel distributed structures
    295  * related to the calling process. The supported commands are:
    296  * - p (cxy)     : display all processes descriptors in a given cluster.
    297  * - s (cxy,lid) : display all threads attached to a given core in a given cluster.
    298  * - v (cxy)     : display the calling process VMM in a given cluster.
    299  * - t (tid)     : display all owner process descriptors attached to a given TXT terminal.
    300  * - x           : force the calling process to exit.
    301  * - c           : continue calling process execution.
    302  *********************************************************************************************
    303  * @ return an integer value between 0 and RAND_MAX.
    304  ********************************************************************************************/
    305 void idbg();
    306 
    307350#endif /* _LIBALMOSMKH_H_ */
    308351
Note: See TracChangeset for help on using the changeset viewer.