source: trunk/kernel/mm/kmem.c @ 635

Last change on this file since 635 was 635, checked in by alain, 5 years ago

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

File size: 7.4 KB
RevLine 
[1]1/*
2 * kmem.c - kernel memory allocator implementation.
3 *
[635]4 * Authors  Alain Greiner (2016,2017,2018,2019)
[1]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
[14]24#include <kernel_config.h>
[457]25#include <hal_kernel_types.h>
[1]26#include <hal_special.h>
27#include <printk.h>
[635]28#include <cluster.h>
[1]29#include <memcpy.h>
30#include <khm.h>
31#include <ppm.h>
[635]32#include <kcm.h>
[1]33#include <page.h>
34#include <kmem.h>
35
[635]36/////////////////////////////////////
37void * kmem_alloc( kmem_req_t * req )
[7]38{
[635]39        uint32_t    type;    // KMEM_PPM / KMEM_KCM / KMEM_KHM
40        uint32_t    flags;   // AF_NONE / AF_ZERO / AF_KERNEL
41        uint32_t    order;   // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes
[1]42
[635]43        type  = req->type;
44        order = req->order;
45        flags = req->flags;
[7]46
[635]47    ////////////////////////////////// PPM
48        if( type == KMEM_PPM )
[159]49        {
[635]50                // allocate the number of requested pages
51                page_t * page_ptr = (void *)ppm_alloc_pages( order );
52
53                if( page_ptr == NULL )
[159]54                {
[635]55                        printk("\n[ERROR] in %s : PPM failed / order %d / cluster %x\n",
56                        __FUNCTION__ , order , local_cxy );
57                        return NULL;
[159]58                }
[7]59
[635]60        xptr_t page_xp = XPTR( local_cxy , page_ptr );
[1]61
[635]62                // reset page if requested
63                if( flags & AF_ZERO ) page_zero( page_ptr );
[619]64
[635]65        // get pointer on buffer from the page descriptor
66        void * ptr = GET_PTR( ppm_page2base( page_xp ) );
[50]67
[438]68#if DEBUG_KMEM
[635]69thread_t * this  = CURRENT_THREAD;
70uint32_t   cycle = (uint32_t)hal_get_cycles();
[438]71if( DEBUG_KMEM < cycle )
[635]72printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n",
73__FUNCTION__, this->process->pid, this->trdid,
741<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), local_cxy, cycle );
[435]75#endif
[635]76        return ptr;
77        }
78    ///////////////////////////////////// KCM
79        else if( type == KMEM_KCM )
[159]80        {
[635]81                // allocate memory from KCM
82                void * ptr = kcm_alloc( order );
[1]83
[180]84                if( ptr == NULL )
85                {
[635]86                        printk("\n[ERROR] in %s : KCM failed / order %d / cluster %x\n",
87                    __FUNCTION__ , order , local_cxy );
[180]88                        return NULL;
89                }
[1]90
[635]91                // reset memory if requested
92                if( flags & AF_ZERO ) memset( ptr , 0 , 1<<order );
[18]93
[438]94#if DEBUG_KMEM
[635]95thread_t * this  = CURRENT_THREAD;
96uint32_t   cycle = (uint32_t)hal_get_cycles();
[438]97if( DEBUG_KMEM < cycle )
[635]98printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n",
[611]99__FUNCTION__, this->process->pid, this->trdid,
[635]1001<<order, ptr, local_cxy, cycle ); 
[433]101#endif
[635]102        return ptr;
[1]103        }
[635]104    //////////////////////////////////// KHM
105        else if( type == KMEM_KHM )
[159]106        {
107                // allocate memory from KHM
[635]108                void * ptr = khm_alloc( &LOCAL_CLUSTER->khm , order );
109
[180]110                if( ptr == NULL )
111                {
[635]112                        printk("\n[ERROR] in %s : KHM failed / order %d / cluster %x\n",
113                        __FUNCTION__ , order , local_cxy );
[180]114                        return NULL;
115                }
[1]116
[159]117                // reset memory if requested
[635]118                if( flags & AF_ZERO ) memset( ptr , 0 , order );
[7]119
[438]120#if DEBUG_KMEM
[635]121thread_t * this  = CURRENT_THREAD;
122uint32_t   cycle = (uint32_t)hal_get_cycles();
[438]123if( DEBUG_KMEM < cycle )
[635]124printk("\n[%s] thread[%x,%x] from KHM / %d bytes / base %x / cxy %x / cycle %d\n",
[611]125__FUNCTION__, this->process->pid, this->trdid, 
[635]126order, ptr, local_cxy, cycle );
[435]127#endif
[635]128        return ptr;
129        }
130    else
131    {
132        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
133        return NULL;
134    }
135}  // end kmem_alloc()
[435]136
[635]137//////////////////////////////////
138void kmem_free( kmem_req_t * req )
139{
140    uint32_t type = req->type;
141
142        if( type == KMEM_PPM )
143        {
144        page_t * page = GET_PTR( ppm_base2page( XPTR( local_cxy , req->ptr ) ) );
145
146        ppm_free_pages( page );
147    }
148    else if( type == KMEM_KCM )
149    {
150        kcm_free( req->ptr );
[1]151        }
[635]152    else if( type == KMEM_KHM )
153    {
154        khm_free( req->ptr );
155    }
156    else
157    {
158        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
159    }
160}  // end kmem_free()
161
162///////////////////////////////////////////
163void * kmem_remote_alloc( cxy_t        cxy,
164                          kmem_req_t * req )
165{
166        uint32_t    type;    // KMEM_PPM / KMEM_KCM / KMEM_KHM
167        uint32_t    flags;   // AF_ZERO / AF_KERNEL / AF_NONE
168        uint32_t    order;   // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes
169
170        type  = req->type;
171        order = req->order;
172        flags = req->flags;
173
174        ///////////////////////////////// PPM
175        if( type == KMEM_PPM )
[159]176        {
[635]177                // allocate the number of requested pages
178                page_t * page_ptr = ppm_remote_alloc_pages( cxy , order );
179
180                if( page_ptr == NULL )
[159]181                {
[635]182                        printk("\n[ERROR] in %s : failed for PPM / order %d in cluster %x\n",
183                        __FUNCTION__ , order , cxy );
184                        return NULL;
185                }
[567]186
[635]187        xptr_t page_xp = XPTR( cxy , page_ptr );
[567]188
[635]189        // get pointer on buffer from the page descriptor
190        xptr_t base_xp = ppm_page2base( page_xp );
[567]191
[635]192                // reset page if requested
193                if( flags & AF_ZERO ) hal_remote_memset( base_xp , 0 , CONFIG_PPM_PAGE_SIZE );
[1]194
[635]195        void * ptr = GET_PTR( base_xp );
196
197#if DEBUG_KMEM_REMOTE
198thread_t * this = CURRENT_THREAD;
199uint32_t   cycle = (uint32_t)hal_get_cycles();
200if( DEBUG_KMEM_REMOTE < cycle )
201printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n",
202__FUNCTION__, this->process->pid, this->trdid,
2031<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), cxy, cycle );
204#endif
205        return ptr;
206        }
207    /////////////////////////////////// KCM
208        else if( type == KMEM_KCM ) 
209        {
[159]210                // allocate memory from KCM
[635]211                void * ptr = kcm_remote_alloc( cxy , order );
212
[180]213                if( ptr == NULL )
214                {
[635]215                        printk("\n[ERROR] in %s : failed for KCM / order %d in cluster %x\n",
216                    __FUNCTION__ , order , cxy );
[180]217                        return NULL;
218                }
[7]219
[159]220                // reset memory if requested
[635]221                if( flags & AF_ZERO )  hal_remote_memset( XPTR( cxy , ptr ) , 0 , 1<<order );
[7]222
[635]223#if DEBUG_KMEM_REMOTE
224thread_t * this = CURRENT_THREAD;
225uint32_t   cycle = (uint32_t)hal_get_cycles();
226if( DEBUG_KMEM_REMOTE < cycle )
227printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n",
228__FUNCTION__, this->process->pid, this->trdid,
2291<<order, ptr, cxy, cycle );
[435]230#endif
[635]231        return ptr;
[1]232        }
[635]233        /////////////////////////////////// KHM
234        else if( type == KMEM_KHM )               
235        {
236        printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__  );
237                return NULL;
238        }
239    else
240    {
241        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
242        return NULL;
243    }
244}  // kmem_remote_malloc()
[1]245
[635]246////////////////////////////////////////
247void kmem_remote_free( cxy_t        cxy,
248                       kmem_req_t * req )
249{
250    uint32_t type = req->type;
[1]251
[635]252        if( type == KMEM_PPM )
[159]253        {
[635]254        page_t * page = GET_PTR( ppm_base2page( XPTR( cxy , req->ptr ) ) );
255
256        ppm_remote_free_pages( cxy , page );
257    }
258    else if( type == KMEM_KCM )
259    {
260        kcm_remote_free( cxy , req->ptr );
[159]261        }
[635]262    else if( type == KMEM_KHM )
263    {
264        printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__ );
265    }
266    else
267    {
268        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
269    }
270}  // end kmem_remote_free()
[18]271
[1]272
273
Note: See TracBrowser for help on using the repository browser.