Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d243f1a8
Commit
d243f1a8
authored
Jul 26, 2002
by
Rusty Russell
Committed by
Linus Torvalds
Jul 26, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Hot-plug CPU Boot Rewrite for PPC
This modifies the PPC boot sequence to "plug in" CPUs one at a time.
parent
58ce9508
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
234 additions
and
55 deletions
+234
-55
arch/ppc/kernel/open_pic.c
arch/ppc/kernel/open_pic.c
+1
-1
arch/ppc/kernel/smp.c
arch/ppc/kernel/smp.c
+162
-10
arch/ppc/platforms/chrp_smp.c
arch/ppc/platforms/chrp_smp.c
+43
-41
arch/ppc/platforms/gemini_setup.c
arch/ppc/platforms/gemini_setup.c
+2
-0
arch/ppc/platforms/iSeries_smp.c
arch/ppc/platforms/iSeries_smp.c
+5
-2
arch/ppc/platforms/pmac_smp.c
arch/ppc/platforms/pmac_smp.c
+4
-0
arch/ppc/platforms/pplus_setup.c
arch/ppc/platforms/pplus_setup.c
+2
-0
arch/ppc/platforms/prep_setup.c
arch/ppc/platforms/prep_setup.c
+2
-0
include/asm-ppc/machdep.h
include/asm-ppc/machdep.h
+8
-0
include/asm-ppc/smp.h
include/asm-ppc/smp.h
+5
-1
No files found.
arch/ppc/kernel/open_pic.c
View file @
d243f1a8
...
@@ -602,7 +602,7 @@ void openpic_request_IPIs(void)
...
@@ -602,7 +602,7 @@ void openpic_request_IPIs(void)
* -- Cort
* -- Cort
*/
*/
void
__init
do_openpic_setup_cpu
(
void
)
void
__
dev
init
do_openpic_setup_cpu
(
void
)
{
{
int
i
;
int
i
;
u32
msk
=
1
<<
smp_hw_index
[
smp_processor_id
()];
u32
msk
=
1
<<
smp_hw_index
[
smp_processor_id
()];
...
...
arch/ppc/kernel/smp.c
View file @
d243f1a8
...
@@ -48,15 +48,17 @@ struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
...
@@ -48,15 +48,17 @@ struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
atomic_t
ipi_recv
;
atomic_t
ipi_recv
;
atomic_t
ipi_sent
;
atomic_t
ipi_sent
;
spinlock_t
kernel_flag
__cacheline_aligned_in_smp
=
SPIN_LOCK_UNLOCKED
;
spinlock_t
kernel_flag
__cacheline_aligned_in_smp
=
SPIN_LOCK_UNLOCKED
;
unsigned
int
prof_multiplier
[
NR_CPUS
];
unsigned
int
prof_multiplier
[
NR_CPUS
]
=
{
[
1
...
NR_CPUS
-
1
]
=
1
}
;
unsigned
int
prof_counter
[
NR_CPUS
];
unsigned
int
prof_counter
[
NR_CPUS
]
=
{
[
1
...
NR_CPUS
-
1
]
=
1
}
;
unsigned
long
cache_decay_ticks
;
unsigned
long
cache_decay_ticks
=
HZ
/
100
;
static
int
max_cpus
__initdata
=
NR_CPUS
;
unsigned
long
cpu_online_map
=
1UL
;
unsigned
long
cpu_
online_map
;
unsigned
long
cpu_
possible_map
=
1UL
;
int
smp_hw_index
[
NR_CPUS
];
int
smp_hw_index
[
NR_CPUS
];
static
struct
smp_ops_t
*
smp_ops
;
struct
thread_info
*
secondary_ti
;
struct
thread_info
*
secondary_ti
;
/* SMP operations for this machine */
static
struct
smp_ops_t
*
smp_ops
;
/* all cpu mappings are 1-1 -- Cort */
/* all cpu mappings are 1-1 -- Cort */
volatile
unsigned
long
cpu_callin_map
[
NR_CPUS
];
volatile
unsigned
long
cpu_callin_map
[
NR_CPUS
];
...
@@ -70,10 +72,6 @@ void smp_call_function_interrupt(void);
...
@@ -70,10 +72,6 @@ void smp_call_function_interrupt(void);
static
int
__smp_call_function
(
void
(
*
func
)
(
void
*
info
),
void
*
info
,
static
int
__smp_call_function
(
void
(
*
func
)
(
void
*
info
),
void
*
info
,
int
wait
,
int
target
);
int
wait
,
int
target
);
#ifdef CONFIG_PPC_ISERIES
extern
void
smp_iSeries_space_timers
(
unsigned
nr
);
#endif
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
*
* Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
* Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
...
@@ -291,6 +289,7 @@ void smp_call_function_interrupt(void)
...
@@ -291,6 +289,7 @@ void smp_call_function_interrupt(void)
atomic_inc
(
&
call_data
->
finished
);
atomic_inc
(
&
call_data
->
finished
);
}
}
#if 0 /* Old boot code. */
void __init smp_boot_cpus(void)
void __init smp_boot_cpus(void)
{
{
int i, cpu_nr;
int i, cpu_nr;
...
@@ -556,3 +555,156 @@ static int __init maxcpus(char *str)
...
@@ -556,3 +555,156 @@ static int __init maxcpus(char *str)
}
}
__setup("maxcpus=", maxcpus);
__setup("maxcpus=", maxcpus);
#else
/* New boot code */
/* FIXME: Do this properly for all archs --RR */
static
spinlock_t
timebase_lock
=
SPIN_LOCK_UNLOCKED
;
static
unsigned
int
timebase_upper
=
0
,
timebase_lower
=
0
;
void
__devinit
smp_generic_give_timebase
(
void
)
{
spin_lock
(
&
timebase_lock
);
do
{
timebase_upper
=
get_tbu
();
timebase_lower
=
get_tbl
();
}
while
(
timebase_upper
!=
get_tbu
());
spin_unlock
(
&
timebase_lock
);
while
(
timebase_upper
||
timebase_lower
)
rmb
();
}
void
__devinit
smp_generic_take_timebase
(
void
)
{
int
done
=
0
;
while
(
!
done
)
{
spin_lock
(
&
timebase_lock
);
if
(
timebase_upper
||
timebase_lower
)
{
set_tb
(
timebase_upper
,
timebase_lower
);
timebase_upper
=
0
;
timebase_lower
=
0
;
done
=
1
;
}
spin_unlock
(
&
timebase_lock
);
}
}
static
void
__devinit
smp_store_cpu_info
(
int
id
)
{
struct
cpuinfo_PPC
*
c
=
&
cpu_data
[
id
];
/* assume bogomips are same for everything */
c
->
loops_per_jiffy
=
loops_per_jiffy
;
c
->
pvr
=
mfspr
(
PVR
);
}
void
__init
smp_prepare_cpus
(
unsigned
int
max_cpus
)
{
int
num_cpus
;
/* Fixup boot cpu */
smp_store_cpu_info
(
smp_processor_id
());
cpu_callin_map
[
smp_processor_id
()]
=
1
;
smp_ops
=
ppc_md
.
smp_ops
;
if
(
smp_ops
==
NULL
)
{
printk
(
"SMP not supported on this machine.
\n
"
);
return
;
}
/* Probe platform for CPUs: always linear. */
num_cpus
=
smp_ops
->
probe
();
cpu_possible_map
=
(
1
<<
num_cpus
)
-
1
;
if
(
smp_ops
->
space_timers
)
smp_ops
->
space_timers
(
num_cpus
);
}
int
__init
setup_profiling_timer
(
unsigned
int
multiplier
)
{
return
0
;
}
/* Processor coming up starts here */
int
__devinit
start_secondary
(
void
*
unused
)
{
int
cpu
;
atomic_inc
(
&
init_mm
.
mm_count
);
current
->
active_mm
=
&
init_mm
;
cpu
=
smp_processor_id
();
smp_store_cpu_info
(
cpu
);
set_dec
(
tb_ticks_per_jiffy
);
cpu_callin_map
[
cpu
]
=
1
;
printk
(
"CPU %i done callin...
\n
"
,
cpu
);
smp_ops
->
setup_cpu
(
cpu
);
printk
(
"CPU %i done setup...
\n
"
,
cpu
);
smp_ops
->
take_timebase
();
printk
(
"CPU %i done timebase take...
\n
"
,
cpu
);
return
cpu_idle
(
NULL
);
}
int
__cpu_up
(
unsigned
int
cpu
)
{
struct
pt_regs
regs
;
struct
task_struct
*
p
;
char
buf
[
32
];
int
c
;
/* create a process for the processor */
/* only regs.msr is actually used, and 0 is OK for it */
memset
(
&
regs
,
0
,
sizeof
(
struct
pt_regs
));
p
=
do_fork
(
CLONE_VM
|
CLONE_IDLETASK
,
0
,
&
regs
,
0
);
if
(
IS_ERR
(
p
))
panic
(
"failed fork for CPU %u: %li"
,
cpu
,
PTR_ERR
(
p
));
init_idle
(
p
,
cpu
);
unhash_process
(
p
);
secondary_ti
=
p
->
thread_info
;
p
->
thread_info
->
cpu
=
cpu
;
/*
* There was a cache flush loop here to flush the cache
* to memory for the first 8MB of RAM. The cache flush
* has been pushed into the kick_cpu function for those
* platforms that need it.
*/
/* wake up cpu */
smp_ops
->
kick_cpu
(
cpu
);
/*
* wait to see if the cpu made a callin (is actually up).
* use this value that I found through experimentation.
* -- Cort
*/
for
(
c
=
1000
;
c
&&
!
cpu_callin_map
[
cpu
];
c
--
)
udelay
(
100
);
if
(
!
cpu_callin_map
[
cpu
])
{
sprintf
(
buf
,
"didn't find cpu %u"
,
cpu
);
if
(
ppc_md
.
progress
)
ppc_md
.
progress
(
buf
,
0x360
+
cpu
);
printk
(
"Processor %u is stuck.
\n
"
,
cpu
);
return
-
ENOENT
;
}
sprintf
(
buf
,
"found cpu %u"
,
cpu
);
if
(
ppc_md
.
progress
)
ppc_md
.
progress
(
buf
,
0x350
+
cpu
);
printk
(
"Processor %d found.
\n
"
,
cpu
);
smp_ops
->
give_timebase
();
set_bit
(
cpu
,
&
cpu_online_map
);
return
0
;
}
void
smp_cpus_done
(
unsigned
int
max_cpus
)
{
smp_ops
->
setup_cpu
(
0
);
}
#endif
arch/ppc/platforms/chrp_smp.c
View file @
d243f1a8
...
@@ -50,59 +50,61 @@ smp_chrp_probe(void)
...
@@ -50,59 +50,61 @@ smp_chrp_probe(void)
return
smp_chrp_cpu_nr
;
return
smp_chrp_cpu_nr
;
}
}
static
void
__init
static
void
__
dev
init
smp_chrp_kick_cpu
(
int
nr
)
smp_chrp_kick_cpu
(
int
nr
)
{
{
*
(
unsigned
long
*
)
KERNELBASE
=
nr
;
*
(
unsigned
long
*
)
KERNELBASE
=
nr
;
asm
volatile
(
"dcbf 0,%0"
::
"r"
(
KERNELBASE
)
:
"memory"
);
asm
volatile
(
"dcbf 0,%0"
::
"r"
(
KERNELBASE
)
:
"memory"
);
}
}
static
void
__init
static
void
__
dev
init
smp_chrp_setup_cpu
(
int
cpu_nr
)
smp_chrp_setup_cpu
(
int
cpu_nr
)
{
{
static
atomic_t
ready
=
ATOMIC_INIT
(
1
);
static
volatile
int
frozen
=
0
;
/* FIXME: Hotplug cpu breaks all this --RR */
if
(
cpu_nr
==
0
)
{
/* wait for all the others */
while
(
atomic_read
(
&
ready
)
<
num_online_cpus
())
barrier
();
atomic_set
(
&
ready
,
1
);
/* freeze the timebase */
call_rtas
(
"freeze-time-base"
,
0
,
1
,
NULL
);
mb
();
frozen
=
1
;
/* XXX assumes this is not a 601 */
set_tb
(
0
,
0
);
last_jiffy_stamp
(
0
)
=
0
;
while
(
atomic_read
(
&
ready
)
<
num_online_cpus
())
barrier
();
/* thaw the timebase again */
call_rtas
(
"thaw-time-base"
,
0
,
1
,
NULL
);
mb
();
frozen
=
0
;
smp_tb_synchronized
=
1
;
}
else
{
atomic_inc
(
&
ready
);
while
(
!
frozen
)
barrier
();
set_tb
(
0
,
0
);
last_jiffy_stamp
(
0
)
=
0
;
mb
();
atomic_inc
(
&
ready
);
while
(
frozen
)
barrier
();
}
if
(
OpenPIC_Addr
)
if
(
OpenPIC_Addr
)
do_openpic_setup_cpu
();
do_openpic_setup_cpu
();
}
}
static
spinlock_t
timebase_lock
=
SPIN_LOCK_UNLOCKED
;
static
unsigned
int
timebase_upper
=
0
,
timebase_lower
=
0
;
void
__devinit
smp_chrp_give_timebase
(
void
)
{
spin_lock
(
&
timebase_lock
);
call_rtas
(
"freeze-time-base"
,
0
,
1
,
NULL
);
timebase_upper
=
get_tbu
();
timebase_lower
=
get_tbl
();
spin_unlock
(
&
timebase_lock
);
while
(
timebase_upper
||
timebase_lower
)
rmb
();
call_rtas
(
"thaw-time-base"
,
0
,
1
,
NULL
);
}
void
__devinit
smp_chrp_take_timebase
(
void
)
{
int
done
=
0
;
while
(
!
done
)
{
spin_lock
(
&
timebase_lock
);
if
(
timebase_upper
||
timebase_lower
)
{
set_tb
(
timebase_upper
,
timebase_lower
);
timebase_upper
=
0
;
timebase_lower
=
0
;
done
=
1
;
}
spin_unlock
(
&
timebase_lock
);
}
printk
(
"CPU %i taken timebase
\n
"
,
smp_processor_id
());
}
/* CHRP with openpic */
/* CHRP with openpic */
struct
smp_ops_t
chrp_smp_ops
__chrpdata
=
{
struct
smp_ops_t
chrp_smp_ops
__chrpdata
=
{
smp_openpic_message_pass
,
.
message_pass
=
smp_openpic_message_pass
,
smp_chrp_probe
,
.
probe
=
smp_chrp_probe
,
smp_chrp_kick_cpu
,
.
kick_cpu
=
smp_chrp_kick_cpu
,
smp_chrp_setup_cpu
,
.
setup_cpu
=
smp_chrp_setup_cpu
,
.
give_timebase
=
smp_chrp_give_timebase
,
.
take_timebase
=
smp_chrp_take_timebase
,
};
};
arch/ppc/platforms/gemini_setup.c
View file @
d243f1a8
...
@@ -528,6 +528,8 @@ static struct smp_ops_t gemini_smp_ops = {
...
@@ -528,6 +528,8 @@ static struct smp_ops_t gemini_smp_ops = {
smp_gemini_probe
,
smp_gemini_probe
,
smp_gemini_kick_cpu
,
smp_gemini_kick_cpu
,
smp_gemini_setup_cpu
,
smp_gemini_setup_cpu
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
#endif
/* CONFIG_SMP */
#endif
/* CONFIG_SMP */
...
...
arch/ppc/platforms/iSeries_smp.c
View file @
d243f1a8
...
@@ -117,7 +117,7 @@ static void smp_iSeries_setup_cpu(int nr)
...
@@ -117,7 +117,7 @@ static void smp_iSeries_setup_cpu(int nr)
set_dec
(
xPaca
[
nr
].
default_decr
);
set_dec
(
xPaca
[
nr
].
default_decr
);
}
}
void
smp_iSeries_space_timers
(
unsigned
nr
)
static
void
smp_iSeries_space_timers
(
unsigned
nr
)
{
{
unsigned
offset
,
i
;
unsigned
offset
,
i
;
...
@@ -131,6 +131,9 @@ struct smp_ops_t iSeries_smp_ops = {
...
@@ -131,6 +131,9 @@ struct smp_ops_t iSeries_smp_ops = {
smp_iSeries_message_pass
,
smp_iSeries_message_pass
,
smp_iSeries_probe
,
smp_iSeries_probe
,
smp_iSeries_kick_cpu
,
smp_iSeries_kick_cpu
,
smp_iSeries_setup_cpu
smp_iSeries_setup_cpu
,
smp_iSeries_space_timers
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
arch/ppc/platforms/pmac_smp.c
View file @
d243f1a8
...
@@ -612,6 +612,8 @@ struct smp_ops_t psurge_smp_ops __pmacdata = {
...
@@ -612,6 +612,8 @@ struct smp_ops_t psurge_smp_ops __pmacdata = {
smp_psurge_probe
,
smp_psurge_probe
,
smp_psurge_kick_cpu
,
smp_psurge_kick_cpu
,
smp_psurge_setup_cpu
,
smp_psurge_setup_cpu
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
/* Core99 Macs (dual G4s) */
/* Core99 Macs (dual G4s) */
...
@@ -620,4 +622,6 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
...
@@ -620,4 +622,6 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
smp_core99_probe
,
smp_core99_probe
,
smp_core99_kick_cpu
,
smp_core99_kick_cpu
,
smp_core99_setup_cpu
,
smp_core99_setup_cpu
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
arch/ppc/platforms/pplus_setup.c
View file @
d243f1a8
...
@@ -309,6 +309,8 @@ static struct smp_ops_t pplus_smp_ops = {
...
@@ -309,6 +309,8 @@ static struct smp_ops_t pplus_smp_ops = {
smp_pplus_probe
,
smp_pplus_probe
,
smp_pplus_kick_cpu
,
smp_pplus_kick_cpu
,
smp_pplus_setup_cpu
,
smp_pplus_setup_cpu
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
#endif
/* CONFIG_SMP */
#endif
/* CONFIG_SMP */
...
...
arch/ppc/platforms/prep_setup.c
View file @
d243f1a8
...
@@ -756,6 +756,8 @@ static struct smp_ops_t prep_smp_ops __prepdata = {
...
@@ -756,6 +756,8 @@ static struct smp_ops_t prep_smp_ops __prepdata = {
smp_prep_probe
,
smp_prep_probe
,
smp_prep_kick_cpu
,
smp_prep_kick_cpu
,
smp_prep_setup_cpu
,
smp_prep_setup_cpu
,
.
give_timebase
=
smp_generic_give_timebase
,
.
take_timebase
=
smp_generic_take_timebase
,
};
};
#endif
/* CONFIG_SMP */
#endif
/* CONFIG_SMP */
...
...
include/asm-ppc/machdep.h
View file @
d243f1a8
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
#define _PPC_MACHDEP_H
#define _PPC_MACHDEP_H
#include <linux/config.h>
#include <linux/config.h>
#include <linux/init.h>
#ifdef CONFIG_APUS
#ifdef CONFIG_APUS
#include <asm-m68k/machdep.h>
#include <asm-m68k/machdep.h>
...
@@ -129,7 +130,14 @@ struct smp_ops_t {
...
@@ -129,7 +130,14 @@ struct smp_ops_t {
int
(
*
probe
)(
void
);
int
(
*
probe
)(
void
);
void
(
*
kick_cpu
)(
int
nr
);
void
(
*
kick_cpu
)(
int
nr
);
void
(
*
setup_cpu
)(
int
nr
);
void
(
*
setup_cpu
)(
int
nr
);
void
(
*
space_timers
)(
int
nr
);
void
(
*
take_timebase
)(
void
);
void
(
*
give_timebase
)(
void
);
};
};
/* Poor default implementations */
extern
void
__devinit
smp_generic_give_timebase
(
void
);
extern
void
__devinit
smp_generic_take_timebase
(
void
);
#endif
/* CONFIG_SMP */
#endif
/* CONFIG_SMP */
#endif
/* _PPC_MACHDEP_H */
#endif
/* _PPC_MACHDEP_H */
...
...
include/asm-ppc/smp.h
View file @
d243f1a8
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
...
@@ -31,11 +32,11 @@ struct cpuinfo_PPC {
...
@@ -31,11 +32,11 @@ struct cpuinfo_PPC {
extern
struct
cpuinfo_PPC
cpu_data
[];
extern
struct
cpuinfo_PPC
cpu_data
[];
extern
unsigned
long
cpu_online_map
;
extern
unsigned
long
cpu_online_map
;
extern
unsigned
long
cpu_possible_map
;
extern
unsigned
long
smp_proc_in_lock
[];
extern
unsigned
long
smp_proc_in_lock
[];
extern
volatile
unsigned
long
cpu_callin_map
[];
extern
volatile
unsigned
long
cpu_callin_map
[];
extern
int
smp_tb_synchronized
;
extern
int
smp_tb_synchronized
;
extern
void
smp_store_cpu_info
(
int
id
);
extern
void
smp_send_tlb_invalidate
(
int
);
extern
void
smp_send_tlb_invalidate
(
int
);
extern
void
smp_send_xmon_break
(
int
cpu
);
extern
void
smp_send_xmon_break
(
int
cpu
);
struct
pt_regs
;
struct
pt_regs
;
...
@@ -48,6 +49,7 @@ extern void smp_local_timer_interrupt(struct pt_regs *);
...
@@ -48,6 +49,7 @@ extern void smp_local_timer_interrupt(struct pt_regs *);
#define smp_processor_id() (current_thread_info()->cpu)
#define smp_processor_id() (current_thread_info()->cpu)
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
#define cpu_possible(cpu) (cpu_possible_map & (1<<(cpu)))
extern
inline
unsigned
int
num_online_cpus
(
void
)
extern
inline
unsigned
int
num_online_cpus
(
void
)
{
{
...
@@ -62,6 +64,8 @@ extern inline int any_online_cpu(unsigned int mask)
...
@@ -62,6 +64,8 @@ extern inline int any_online_cpu(unsigned int mask)
return
-
1
;
return
-
1
;
}
}
extern
int
__cpu_up
(
unsigned
int
cpu
);
extern
int
smp_hw_index
[];
extern
int
smp_hw_index
[];
#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment