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

Last change on this file since 690 was 683, checked in by alain, 3 years ago

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File size: 5.5 KB
Line 
1/*
2 * core.c - core descriptor access function.
3 *
4 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *         Alain Greiner    (2016,2017,2018,2019,2020)
6 *
7 * Copyright (c) UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <kernel_config.h>
26#include <hal_kernel_types.h>
27#include <hal_special.h>
28#include <printk.h>
29#include <thread.h>
30#include <chdev.h>
31#include <alarm.h>
32#include <dev_pic.h>
33#include <rpc.h>
34#include <cluster.h>
35#include <kmem.h>
36#include <core.h>
37
38/////////////////////////////////
39void core_init( core_t    * core,
40                lid_t       lid,
41                gid_t       gid )
42{
43        core->lid               = lid;
44        core->gid               = gid;
45        core->cycles            = 0;
46        core->time_stamp        = 0;
47        core->ticks_nr          = 0;
48        core->usage             = 0;
49        core->fpu_owner         = NULL;
50        core->rand_last         = hal_time_stamp() & 0xFFF;
51
52    // initialize the scheduler
53        sched_init( core );
54
55    // initialise the alarms lock
56    remote_busylock_init( XPTR( local_cxy , &core->alarms_lock ) , LOCK_CORE_ALARMS );
57
58    // initialise the alarms list
59    list_root_init( &core->alarms_root );
60}
61
62////////////////////////////////////////////////////////////////////////////////////
63// This static function checks the alarms registered in the core, and calls the
64// relevant alarm handler for all alarms whose time is elapded.
65// It does not take the lock protecting the alarm list, because it access only
66// the first alarm in the list, and all modifications in he list are done
67// the low level access functions called by the handler(s).
68////////////////////////////////////////////////////////////////////////////////////
69static void core_check_alarms( core_t * core )
70{
71    alarm_handler_t * handler;
72
73    // get pointer on root of alarms list
74    list_entry_t * root = &core->alarms_root;
75
76    // does nothing if list is empty
77    if( list_is_empty( root ) ) return;
78
79    while( 1 )
80    {
81        // get pointer on first alarm
82        alarm_t * alarm = LIST_FIRST( root , alarm_t , list );
83
84        // get first alarm date
85        cycle_t alarm_date = alarm->date; 
86
87        // get current date
88        cycle_t current_date = hal_get_cycles();
89
90        // call handler if delay elapsed, and retry
91        if( current_date >= alarm_date )
92        {
93            // get pointer on registered alarm handler
94            handler = (alarm_handler_t *)alarm->func_ptr;
95
96            // call alarm handler
97            handler( alarm->args_xp );
98        }
99        else   // exit loop when first alarm delay not elapsed
100        {
101            break;
102        }
103    }
104}   // end core_check_alarms()
105
106//////////////////////
107lid_t core_lid( void )
108{
109    uint32_t    i;
110
111    // get pointer on local cluser descriptor
112    cluster_t * cluster = LOCAL_CLUSTER;
113
114    // get core gid from hardware register
115    gid_t gid = hal_get_gid();
116
117    // makes an associative search in core_tbl[] from gid
118    for( i = 0 ; i < cluster->cores_nr ; i++ )
119    {
120        if( gid == cluster->core_tbl[i].gid ) return i;
121    }
122
123    assert( __FUNCTION__, false , "core not found" );
124
125    return 0;
126}
127
128//////////////////////////////////////////////
129inline uint32_t core_get_rand( core_t * core )
130{
131        uint32_t value  = ((core->rand_last * CONFIG_RDNG_PARAM_A) +
132                            CONFIG_RDNG_PARAM_C) ^ (hal_get_cycles() & 0xFFF);
133        core->rand_last = value;
134        return value;
135}
136
137////////////////////////////////////
138void core_get_time( core_t   * core,
139                    uint32_t * tm_s, 
140                    uint32_t * tm_us )
141{
142    // get number of cycles
143    uint64_t cycles = core->cycles;
144
145    // get number of cycles per second
146    uint32_t cycles_per_second = LOCAL_CLUSTER->sys_clk;
147
148    *tm_s  = cycles / cycles_per_second;
149    *tm_us = (cycles * 1000000) % cycles_per_second;
150}
151
152////////////////////////////////
153void core_clock( core_t * core )
154{
155        uint32_t ticks;
156
157        // update ticks counter
158        ticks = core->ticks_nr++;
159
160    // handle alarms
161    core_check_alarms( core );
162
163        // handle scheduler
164        if( (ticks % CONFIG_SCHED_TICKS_PER_QUANTUM) == 0 ) sched_yield( "TICK");
165}
166
167////////////////////////////////////////
168void core_compute_stats( core_t * core )
169{
170        thread_t * idle  = core->scheduler.idle;
171        uint32_t   ticks = core->ticks_nr;
172
173        uint32_t   idle_percent;
174        uint32_t   busy_percent;
175        uint32_t   usage;
176
177        // compute cumulated usage
178        ticks         = (ticks) ? ticks : 1;
179        idle_percent  = (idle->ticks_nr * 100) / ticks;
180        idle_percent  = (idle_percent > 100) ? 100 : idle_percent;
181        busy_percent  = 100 - idle_percent;
182        usage         = (busy_percent + core->usage) / 2;
183
184        // update core descriptor
185        core->usage = usage;
186        hal_fence();
187
188        core->ticks_nr = 0;
189        idle->ticks_nr = 0;
190}
191
192/////////////////////////////////////
193void core_reset_stats( core_t * core )
194{
195        thread_t * idle  = core->scheduler.idle;
196
197        core->ticks_nr = 0;
198        core->usage    = 0;
199        idle->ticks_nr = 0;
200
201        hal_fence();
202}
203
Note: See TracBrowser for help on using the repository browser.