source: trunk/kernel/kern/core.c @ 4

Last change on this file since 4 was 1, checked in by alain, 8 years ago

First import

File size: 6.4 KB
Line 
1/*
2 * core.c - core descriptor access function.
3 *
4 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *         Mohamed Lamine Karaoui (2015)
6 *         Alain Greiner (2016)
7 *
8 * Copyright (c) UPMC Sorbonne Universites
9 *
10 * This file is part of ALMOS-MKH.
11 *
12 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2.0 of the License.
15 *
16 * ALMOS-MKH is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <almos_config.h>
27#include <hal_types.h>
28#include <hal_special.h>
29#include <errno.h>
30#include <printk.h>
31#include <thread.h>
32#include <dev_icu.h>
33#include <rpc.h>
34#include <cluster.h>
35#include <kmem.h>
36#include <sysfs.h>
37#include <dqdt.h>
38#include <core.h>
39
40
41/////////////////////////////////
42void core_init( core_t    * core, 
43                uint32_t    lid, 
44                uint32_t    gid )
45{
46        core->lid               = lid;
47        core->gid               = gid;
48        core->cycles            = 0;
49        core->time_stamp        = 0;
50        core->ticks_nr          = 0;
51        core->ticks_period      = CONFIG_SCHED_TICK_PERIOD;
52        core->usage             = 0;
53        core->spurious_irqs     = 0;
54    core->rpc_threads       = 0;
55
56        rpc_fifo_init( &core->rpc_fifo );
57
58    list_root_init( &core->rpc_free_list );
59
60    core->thread_rpc        = NULL;
61    core->thread_idle       = NULL;
62    core->fpu_owner         = NULL;
63        core->rand_last         =  hal_time_stamp() & 0xFFF;
64
65        sched_init( core );
66
67        core->icu               = NULL;          // TODO ??? [AG]
68}
69
70//////////////////////////////////////////////
71inline uint32_t core_get_rand( core_t * core )
72{
73    uint32_t value  = ((core->rand_last * CONFIG_RDNG_PARAM_A) +
74                        CONFIG_RDNG_PARAM_C) ^ (hal_time_stamp() & 0xFFF);
75    core->rand_last = value;
76    return value;
77}
78
79////////////////////////////////////////////////
80inline uint64_t core_get_cycles( core_t * core )
81{
82    uint32_t elapsed;
83    uint64_t cycles;
84        uint32_t time_stamp = core->time_stamp;
85        uint32_t time_now   = hal_time_stamp();
86       
87        // compute number of elapsed cycles, taking into account 32 bits register wrap
88        if(time_now < time_stamp) elapsed = (0xFFFFFFFF - time_stamp) + time_now;
89        else                      elapsed = (time_now - time_stamp);
90
91    cycles = core->cycles + elapsed;
92
93    // update core time
94    core->time_stamp = time_now;
95    core->cycles     = cycles;
96        hal_wbflush();
97
98        return cycles;
99}
100
101////////////////////////////////////
102void core_get_time( core_t   * core,
103                    uint32_t * tm_ms, 
104                    uint32_t * tm_us )
105{
106        // uint64_t cycles = core_get_cycles( core );
107
108    // TODO ces deux ligne ne compilent pas : "undefined referenc to __udivdi3"
109
110        // *tm_ms = (cycles / CONFIG_CYCLES_PER_MS);
111        // *tm_us = (cycles % CONFIG_CYCLES_PER_MS) / (CONFIG_CYCLES_PER_MS / 1000000);
112
113    printk("\n[PANIC] in %s : not implemented yet\n", __FUNCTION__ );
114}
115
116//////////////////////////////////////
117void core_time_update( core_t * core )
118{
119    uint32_t elapsed;
120        uint32_t ticks_nr   = core->ticks_nr;
121        uint64_t cycles     = core->cycles;
122        uint32_t time_stamp = core->time_stamp;
123        uint32_t time_now   = hal_time_stamp();
124
125    // compute number of elapsed cycles taking into account 32 bits register wrap
126        if( time_now < time_stamp ) elapsed = (0xFFFFFFFF - time_stamp) + time_now;
127        else                        elapsed = time_now - time_stamp;
128   
129        cycles  += elapsed;
130        ticks_nr = elapsed / core->ticks_period;
131
132        core->time_stamp     = time_now;
133        core->cycles         = cycles + elapsed;
134        core->ticks_nr       = ticks_nr + (elapsed / core->ticks_period);
135        hal_wbflush();
136}
137
138////////////////////////////////
139void core_clock( core_t * core )
140{
141        uint32_t ticks;
142
143    // update cycles and ticks counter
144        core_time_update( core );
145
146    // get current ticks number
147        ticks = core->ticks_nr;
148
149    // handle pending alarms TODO ??? [AG]
150        // alarm_clock( &core->alarm_mgr , ticks );
151
152    // handle scheduler TODO  improve the scheduling condition ... AG
153    if( (ticks % 10) == 0 ) sched_yield();
154       
155    // update DQDT TODO  This update should depend on the cluster identifier,
156    // to avoid simultaneous updates from various clusters ... AG
157        if( ((ticks % CONFIG_DQDT_PERIOD) == 0) && (core->lid == 0) ) dqdt_global_update();
158}
159
160////////////////////////////////////////
161void core_compute_stats( core_t * core ) 
162{
163        thread_t * idle  = core->thread_idle;
164        uint32_t   ticks = core->ticks_nr;
165
166        uint32_t   idle_percent;
167        uint32_t   busy_percent;
168        uint32_t   usage;
169
170    // compute cumulated usage       
171        ticks         = (ticks) ? ticks : 1;
172        idle_percent  = (idle->ticks_nr * 100) / ticks;
173        idle_percent  = (idle_percent > 100) ? 100 : idle_percent;
174        busy_percent  = 100 - idle_percent;
175        usage         = (busy_percent + core->usage) / 2;
176
177    // update core descriptor
178        core->usage = usage;
179        hal_wbflush();
180
181#if CONFIG_SHOW_CPU_USAGE
182        printk(INFO, "INFO: core %d in cluster %x : busy_percent = %d / cumulated_usage = %d\n",
183               core->lid, local_cxy , busy_percent , usage );
184#endif
185
186        core->ticks_nr = 0;
187        idle->ticks_nr = 0;
188}
189
190/////////////////////////////////////
191void core_reset_stats( core_t * core )
192{
193        core_time_update(core);
194
195        core->ticks_nr              = 0;
196        core->usage                 = 0;
197        core->thread_idle->ticks_nr = 0;
198        hal_wbflush();
199}
200
201///////////////////////////////////////////////////
202void core_set_irq_vector_entry( xptr_t     core_xp,
203                                uint32_t   irq_type,
204                                uint32_t   irq_id,
205                                xptr_t     dev_xp )
206{
207    // get core cluster and local pointer
208    cxy_t    core_cxy = GET_CXY( core_xp );
209    core_t * core_ptr = (core_t *)GET_PTR( core_xp );
210
211    // compute xptr on relevant interrupt vector entry
212    xptr_t   xp;
213    if     ( irq_type == WTI_TYPE ) xp = XPTR( core_cxy , &core_ptr->wti_vector[irq_id] );
214    else if( irq_type == HWI_TYPE ) xp = XPTR( core_cxy , &core_ptr->hwi_vector[irq_id] );
215    else                            xp = XPTR( core_cxy , &core_ptr->pti_vector[irq_id] );
216
217    // set relevant IRQ vector entry
218    hal_remote_swd( xp , dev_xp );
219}
Note: See TracBrowser for help on using the repository browser.