diff options
author | akolb <none@none> | 2008-03-26 21:07:48 -0700 |
---|---|---|
committer | akolb <none@none> | 2008-03-26 21:07:48 -0700 |
commit | 0b70c4673a08649be68425e869e9d6357ea777a4 (patch) | |
tree | 732cf84e22666b6a803adf00ea6755970c401e76 /usr/src | |
parent | 78ed97a7b79b59ef2ef41f190c9be35c54d90119 (diff) | |
download | illumos-joyent-0b70c4673a08649be68425e869e9d6357ea777a4.tar.gz |
PSARC 2008/138 Soft CPU and processor set bindings
6656791 Weaker CPU and processor set bindings is useful
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/disp/cpupart.c | 116 | ||||
-rw-r--r-- | usr/src/uts/common/disp/thread.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/cpu.c | 69 | ||||
-rw-r--r-- | usr/src/uts/common/os/lwp.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/cpuvar.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/processor.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/pset.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/sys/thread.h | 18 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/processor_bind.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/pset.c | 29 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mlsetup.c | 3 | ||||
-rw-r--r-- | usr/src/uts/sun4/os/mlsetup.c | 3 |
12 files changed, 217 insertions, 54 deletions
diff --git a/usr/src/uts/common/disp/cpupart.c b/usr/src/uts/common/disp/cpupart.c index ecd5aff873..715813600e 100644 --- a/usr/src/uts/common/disp/cpupart.c +++ b/usr/src/uts/common/disp/cpupart.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -100,6 +100,9 @@ static uint_t cp_max_numparts; #define PSTOCP(psid) ((cpupartid_t)((psid) == PS_NONE ? CP_DEFAULT : (psid))) #define CPTOPS(cpid) ((psetid_t)((cpid) == CP_DEFAULT ? PS_NONE : (cpid))) + +static int cpupart_unbind_threads(cpupart_t *, boolean_t); + /* * Find a CPU partition given a processor set ID. */ @@ -284,6 +287,7 @@ cpupart_move_cpu(cpu_t *cp, cpupart_t *newpp, int forced) int lgrp_diff_lpl; lpl_t *cpu_lpl; int ret; + boolean_t unbind_all_threads = (forced != 0); ASSERT(MUTEX_HELD(&cpu_lock)); ASSERT(newpp != NULL); @@ -309,11 +313,38 @@ cpupart_move_cpu(cpu_t *cp, cpupart_t *newpp, int forced) */ move_threads = 0; } else if (oldpp->cp_ncpus == 1) { - cpu_state_change_notify(cp->cpu_id, CPU_CPUPART_IN); - return (EBUSY); + /* + * The last CPU is removed from a partition which has threads + * running in it. Some of these threads may be bound to this + * CPU. + * + * Attempt to unbind threads from the CPU and from the processor + * set. Note that no threads should be bound to this CPU since + * cpupart_move_threads will refuse to move bound threads to + * other CPUs. + */ + (void) cpu_unbind(oldpp->cp_cpulist->cpu_id, B_FALSE); + (void) cpupart_unbind_threads(oldpp, B_FALSE); + + if (!disp_bound_partition(cp, 0)) { + /* + * No bound threads in this partition any more + */ + move_threads = 0; + } else { + /* + * There are still threads bound to the partition + */ + cpu_state_change_notify(cp->cpu_id, CPU_CPUPART_IN); + return (EBUSY); + } } - if (forced && (ret = cpu_unbind(cp->cpu_id)) != 0) { + /* + * If forced flag is set unbind any threads from this CPU. + * Otherwise unbind soft-bound threads only. + */ + if ((ret = cpu_unbind(cp->cpu_id, unbind_all_threads)) != 0) { cpu_state_change_notify(cp->cpu_id, CPU_CPUPART_IN); return (ret); } @@ -798,26 +829,23 @@ cpupart_create(psetid_t *psid) return (0); } - /* - * Destroy a partition. + * Move threads from specified partition to cp_default. If `force' is specified, + * move all threads, otherwise move only soft-bound threads. */ -int -cpupart_destroy(psetid_t psid) +static int +cpupart_unbind_threads(cpupart_t *pp, boolean_t unbind_all) { - cpu_t *cp, *first_cp; - cpupart_t *pp, *newpp; - int err = 0; void *projbuf, *zonebuf; kthread_t *t; proc_t *p; + int err = 0; + psetid_t psid = pp->cp_id; ASSERT(pool_lock_held()); - mutex_enter(&cpu_lock); + ASSERT(MUTEX_HELD(&cpu_lock)); - pp = cpupart_find(psid); if (pp == NULL || pp == &cp_default) { - mutex_exit(&cpu_lock); return (EINVAL); } @@ -829,10 +857,6 @@ cpupart_destroy(psetid_t psid) projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ); zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE); - /* - * First need to unbind all the threads currently bound to the - * partition. Then do the actual destroy (which moves the CPUs). - */ mutex_enter(&pidlock); t = curthread; do { @@ -847,17 +871,23 @@ again: p = ttoproc(t); mutex_exit(&p->p_lock); goto again; } - err = cpupart_bind_thread(t, PS_NONE, 1, - projbuf, zonebuf); - if (err) { - mutex_exit(&p->p_lock); - mutex_exit(&pidlock); - mutex_exit(&cpu_lock); - fss_freebuf(projbuf, FSS_ALLOC_PROJ); - fss_freebuf(zonebuf, FSS_ALLOC_ZONE); - return (err); + + /* + * Can only unbind threads which have revocable binding + * unless force unbinding requested. + */ + if (unbind_all || TB_PSET_IS_SOFT(t)) { + err = cpupart_bind_thread(t, PS_NONE, 1, + projbuf, zonebuf); + if (err) { + mutex_exit(&p->p_lock); + mutex_exit(&pidlock); + fss_freebuf(projbuf, FSS_ALLOC_PROJ); + fss_freebuf(zonebuf, FSS_ALLOC_ZONE); + return (err); + } + t->t_bind_pset = PS_NONE; } - t->t_bind_pset = PS_NONE; mutex_exit(&p->p_lock); } t = t->t_next; @@ -866,6 +896,36 @@ again: p = ttoproc(t); mutex_exit(&pidlock); fss_freebuf(projbuf, FSS_ALLOC_PROJ); fss_freebuf(zonebuf, FSS_ALLOC_ZONE); + return (err); +} + +/* + * Destroy a partition. + */ +int +cpupart_destroy(psetid_t psid) +{ + cpu_t *cp, *first_cp; + cpupart_t *pp, *newpp; + int err = 0; + + ASSERT(pool_lock_held()); + mutex_enter(&cpu_lock); + + pp = cpupart_find(psid); + if (pp == NULL || pp == &cp_default) { + mutex_exit(&cpu_lock); + return (EINVAL); + } + + /* + * Unbind all the threads currently bound to the partition. + */ + err = cpupart_unbind_threads(pp, B_TRUE); + if (err) { + mutex_exit(&cpu_lock); + return (err); + } newpp = &cp_default; while ((cp = pp->cp_cpulist) != NULL) { diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c index 27e6034f05..0d4fd8e26c 100644 --- a/usr/src/uts/common/disp/thread.c +++ b/usr/src/uts/common/disp/thread.c @@ -107,6 +107,9 @@ int lwp_cache_sz = 32; int t_cache_sz = 8; static kt_did_t next_t_id = 1; +/* Default mode for thread binding to CPUs and processor sets */ +int default_binding_mode = TB_ALLHARD; + /* * Min/Max stack sizes for stack size parameters */ @@ -419,6 +422,7 @@ thread_create( t->t_stime = lbolt; t->t_schedflag = TS_LOAD | TS_DONT_SWAP; t->t_bind_cpu = PBIND_NONE; + t->t_bindflag = (uchar_t)default_binding_mode; t->t_bind_pset = PS_NONE; t->t_plockp = &pp->p_lock; t->t_copyops = NULL; diff --git a/usr/src/uts/common/os/cpu.c b/usr/src/uts/common/os/cpu.c index 80c2198c80..a06b5fb189 100644 --- a/usr/src/uts/common/os/cpu.c +++ b/usr/src/uts/common/os/cpu.c @@ -1231,6 +1231,7 @@ cpu_offline(cpu_t *cp, int flags) lpl_t *cpu_lpl; proc_t *p; int lgrp_diff_lpl; + boolean_t unbind_all_threads = (flags & CPU_FORCED) != 0; ASSERT(MUTEX_HELD(&cpu_lock)); @@ -1258,9 +1259,11 @@ cpu_offline(cpu_t *cp, int flags) if (ncpus_online <= 1 || pp->cp_ncpus <= 1 || cpu_intr_count(cp) < 2) return (EBUSY); /* - * Unbind all thread bound to our CPU if we were asked to. + * Unbind all soft-bound threads bound to our CPU and hard bound threads + * if we were asked to. */ - if (flags & CPU_FORCED && (error = cpu_unbind(cp->cpu_id)) != 0) + error = cpu_unbind(cp->cpu_id, unbind_all_threads); + if (error != 0) return (error); /* * We shouldn't be bound to this CPU ourselves. @@ -2434,7 +2437,7 @@ cpu_bind_thread(kthread_id_t tp, processorid_t bind, processorid_t *obind, int *error) { processorid_t binding; - cpu_t *cp; + cpu_t *cp = NULL; ASSERT(MUTEX_HELD(&cpu_lock)); ASSERT(MUTEX_HELD(&ttoproc(tp)->p_lock)); @@ -2447,12 +2450,47 @@ cpu_bind_thread(kthread_id_t tp, processorid_t bind, processorid_t *obind, * reporting PBIND_NONE for a process when some LWPs are bound. */ binding = tp->t_bind_cpu; - if (binding != PBIND_NONE) - *obind = binding; /* record old binding */ - if (bind == PBIND_QUERY) { + switch (bind) { + case PBIND_QUERY: + /* Just return the old binding */ + *obind = binding; + thread_unlock(tp); + return (0); + + case PBIND_QUERY_TYPE: + /* Return the binding type */ + *obind = TB_CPU_IS_SOFT(tp) ? PBIND_SOFT : PBIND_HARD; + thread_unlock(tp); + return (0); + + case PBIND_SOFT: + /* + * Set soft binding for this thread and return the actual + * binding + */ + TB_CPU_SOFT_SET(tp); + *obind = binding; + thread_unlock(tp); + return (0); + + case PBIND_HARD: + /* + * Set hard binding for this thread and return the actual + * binding + */ + TB_CPU_HARD_SET(tp); + *obind = binding; thread_unlock(tp); return (0); + + case PBIND_NONE: + break; + + default: + /* record old binding */ + *obind = binding; + break; } /* @@ -2472,11 +2510,11 @@ cpu_bind_thread(kthread_id_t tp, processorid_t bind, processorid_t *obind, binding = bind; if (binding != PBIND_NONE) { - cp = cpu[binding]; + cp = cpu_get((processorid_t)binding); /* - * Make sure binding is in right partition. + * Make sure binding is valid and is in right partition. */ - if (tp->t_cpupart != cp->cpu_part) { + if (cp == NULL || tp->t_cpupart != cp->cpu_part) { *error = EINVAL; thread_unlock(tp); return (0); @@ -2702,10 +2740,13 @@ cpuset_bounds(cpuset_t *s, uint_t *smallestid, uint_t *largestid) #endif /* CPUSET_WORDS */ /* - * Unbind all user threads bound to a given CPU. + * Unbind threads bound to specified CPU. + * + * If `unbind_all_threads' is true, unbind all user threads bound to a given + * CPU. Otherwise unbind all soft-bound user threads. */ int -cpu_unbind(processorid_t cpu) +cpu_unbind(processorid_t cpu, boolean_t unbind_all_threads) { processorid_t obind; kthread_t *tp; @@ -2731,6 +2772,12 @@ cpu_unbind(processorid_t cpu) do { if (tp->t_bind_cpu != cpu) continue; + /* + * Skip threads with hard binding when + * `unbind_all_threads' is not specified. + */ + if (!unbind_all_threads && TB_CPU_IS_HARD(tp)) + continue; err = cpu_bind_thread(tp, PBIND_NONE, &obind, &berr); if (ret == 0) ret = err; diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c index 39ca56ac7d..d80f32c658 100644 --- a/usr/src/uts/common/os/lwp.c +++ b/usr/src/uts/common/os/lwp.c @@ -346,12 +346,15 @@ grow: t->t_bind_cpu = binding = PBIND_NONE; t->t_cpupart = oldpart = &cp_default; t->t_bind_pset = PS_NONE; + t->t_bindflag = (uchar_t)default_binding_mode; } else { binding = curthread->t_bind_cpu; t->t_bind_cpu = binding; oldpart = t->t_cpupart; t->t_cpupart = curthread->t_cpupart; t->t_bind_pset = curthread->t_bind_pset; + t->t_bindflag = curthread->t_bindflag | + (uchar_t)default_binding_mode; } /* diff --git a/usr/src/uts/common/sys/cpuvar.h b/usr/src/uts/common/sys/cpuvar.h index c7b76b32ea..cd0d027866 100644 --- a/usr/src/uts/common/sys/cpuvar.h +++ b/usr/src/uts/common/sys/cpuvar.h @@ -668,7 +668,7 @@ void cpu_destroy_bound_threads(cpu_t *cp); extern int cpu_bind_thread(kthread_t *tp, processorid_t bind, processorid_t *obind, int *error); -extern int cpu_unbind(processorid_t cpu_id); +extern int cpu_unbind(processorid_t cpu_id, boolean_t force); extern void thread_affinity_set(kthread_t *t, int cpu_id); extern void thread_affinity_clear(kthread_t *t); extern void affinity_set(int cpu_id); diff --git a/usr/src/uts/common/sys/processor.h b/usr/src/uts/common/sys/processor.h index 4d6f90e988..3a76c8c9b4 100644 --- a/usr/src/uts/common/sys/processor.h +++ b/usr/src/uts/common/sys/processor.h @@ -25,7 +25,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -106,6 +106,9 @@ typedef struct { */ #define PBIND_NONE -1 /* LWP/thread is not bound */ #define PBIND_QUERY -2 /* don't set, just return the binding */ +#define PBIND_HARD -3 /* prevents offlining CPU (default) */ +#define PBIND_SOFT -4 /* allows offlining CPU */ +#define PBIND_QUERY_TYPE -5 /* Return binding type */ /* * User-level system call interface prototypes diff --git a/usr/src/uts/common/sys/pset.h b/usr/src/uts/common/sys/pset.h index 395b3850a8..f98e327620 100644 --- a/usr/src/uts/common/sys/pset.h +++ b/usr/src/uts/common/sys/pset.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,6 +44,9 @@ typedef int psetid_t; #define PS_NONE -1 #define PS_QUERY -2 #define PS_MYID -3 +#define PS_SOFT -4 +#define PS_HARD -5 +#define PS_QUERY_TYPE -6 /* types of processor sets */ #define PS_SYSTEM 1 diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h index 6fced086b3..eee18d53f9 100644 --- a/usr/src/uts/common/sys/thread.h +++ b/usr/src/uts/common/sys/thread.h @@ -125,6 +125,7 @@ typedef struct _kthread { pri_t t_epri; /* inherited thread priority */ pri_t t_cpri; /* thread scheduling class priority */ char t_writer; /* sleeping in lwp_rwlock_lock(RW_WRITE_LOCK) */ + uchar_t t_bindflag; /* CPU and pset binding type */ label_t t_pcb; /* pcb, save area when switching */ lwpchan_t t_lwpchan; /* reason for blocking */ #define t_wchan0 t_lwpchan.lc_wchan0 @@ -415,6 +416,21 @@ typedef struct _kthread { #define TS_ANYWAITQ (TS_PROJWAITQ|TS_ZONEWAITQ) /* + * Thread binding types + */ +#define TB_ALLHARD 0 +#define TB_CPU_SOFT 0x01 /* soft binding to CPU */ +#define TB_PSET_SOFT 0x02 /* soft binding to pset */ + +#define TB_CPU_SOFT_SET(t) ((t)->t_bindflag |= TB_CPU_SOFT) +#define TB_CPU_HARD_SET(t) ((t)->t_bindflag &= ~TB_CPU_SOFT) +#define TB_PSET_SOFT_SET(t) ((t)->t_bindflag |= TB_PSET_SOFT) +#define TB_PSET_HARD_SET(t) ((t)->t_bindflag &= ~TB_PSET_SOFT) +#define TB_CPU_IS_SOFT(t) ((t)->t_bindflag & TB_CPU_SOFT) +#define TB_CPU_IS_HARD(t) (!TB_CPU_IS_SOFT(t)) +#define TB_PSET_IS_SOFT(t) ((t)->t_bindflag & TB_PSET_SOFT) + +/* * No locking needed for AST field. */ #define aston(t) ((t)->t_astflag = 1) @@ -564,6 +580,8 @@ extern disp_lock_t stop_lock; /* lock protecting stopped threads */ caddr_t thread_stk_init(caddr_t); /* init thread stack */ +extern int default_binding_mode; + #endif /* _KERNEL */ /* diff --git a/usr/src/uts/common/syscall/processor_bind.c b/usr/src/uts/common/syscall/processor_bind.c index 129129d7d1..7ff855a86b 100644 --- a/usr/src/uts/common/syscall/processor_bind.c +++ b/usr/src/uts/common/syscall/processor_bind.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,6 +219,9 @@ processor_bind(idtype_t idtype, id_t id, processorid_t bind, case PBIND_NONE: case PBIND_QUERY: + case PBIND_HARD: + case PBIND_SOFT: + case PBIND_QUERY_TYPE: break; } @@ -333,7 +336,7 @@ processor_bind(idtype_t idtype, id_t id, processorid_t bind, if (id == P_MYID || bind != PBIND_NONE || cpu_get(id) == NULL) ret = EINVAL; else - ret = cpu_unbind(id); + ret = cpu_unbind(id, B_TRUE); break; case P_ALL: @@ -345,7 +348,7 @@ processor_bind(idtype_t idtype, id_t id, processorid_t bind, do { if ((cp->cpu_flags & CPU_EXISTS) == 0) continue; - i = cpu_unbind(cp->cpu_id); + i = cpu_unbind(cp->cpu_id, B_TRUE); if (ret == 0) ret = i; } while ((cp = cp->cpu_next) != cpu_list); diff --git a/usr/src/uts/common/syscall/pset.c b/usr/src/uts/common/syscall/pset.c index 767529fc5d..b0427e009e 100644 --- a/usr/src/uts/common/syscall/pset.c +++ b/usr/src/uts/common/syscall/pset.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -251,7 +251,24 @@ pset_bind_thread(kthread_t *tp, psetid_t pset, psetid_t *oldpset, void *projbuf, ASSERT(MUTEX_HELD(&ttoproc(tp)->p_lock)); *oldpset = tp->t_bind_pset; - if (pset != PS_QUERY) { + + switch (pset) { + case PS_SOFT: + TB_PSET_SOFT_SET(tp); + break; + + case PS_HARD: + TB_PSET_HARD_SET(tp); + break; + + case PS_QUERY: + break; + + case PS_QUERY_TYPE: + *oldpset = TB_PSET_IS_SOFT(tp) ? PS_SOFT : PS_HARD; + break; + + default: /* * Must have the same UID as the target process or * have PRIV_PROC_OWNER privilege. @@ -273,7 +290,10 @@ pset_bind_thread(kthread_t *tp, psetid_t pset, psetid_t *oldpset, void *projbuf, if ((error = cpupart_bind_thread(tp, pset, 0, projbuf, zonebuf)) == 0) tp->t_bind_pset = pset; + + break; } + return (error); } @@ -285,7 +305,7 @@ pset_bind_process(proc_t *pp, psetid_t pset, psetid_t *oldpset, void *projbuf, kthread_t *tp; /* skip kernel processes */ - if (pset != PS_QUERY && pp->p_flag & SSYS) { + if ((pset != PS_QUERY) && pp->p_flag & SSYS) { *oldpset = PS_NONE; return (0); } @@ -463,7 +483,8 @@ pset_bind(psetid_t pset, idtype_t idtype, id_t id, psetid_t *opset) void *projbuf, *zonebuf; pool_lock(); - if (pset != PS_QUERY) { + if ((pset != PS_QUERY) && (pset != PS_SOFT) && + (pset != PS_HARD) && (pset != PS_QUERY_TYPE)) { /* * Check if the set actually exists before checking * permissions. This is the historical error diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index f33f60e320..c099fc9764 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -241,6 +241,7 @@ mlsetup(struct regs *rp) t0.t_disp_queue = &cpu0_disp; t0.t_bind_cpu = PBIND_NONE; t0.t_bind_pset = PS_NONE; + t0.t_bindflag = (uchar_t)default_binding_mode; t0.t_cpupart = &cp_default; t0.t_clfuncs = &sys_classfuncs.thread; t0.t_copyops = NULL; diff --git a/usr/src/uts/sun4/os/mlsetup.c b/usr/src/uts/sun4/os/mlsetup.c index 6cefe6cc99..db8066c8ca 100644 --- a/usr/src/uts/sun4/os/mlsetup.c +++ b/usr/src/uts/sun4/os/mlsetup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -162,6 +162,7 @@ mlsetup(struct regs *rp, kfpu_t *fp) t0.t_disp_queue = &cpu0_disp; t0.t_bind_cpu = PBIND_NONE; t0.t_bind_pset = PS_NONE; + t0.t_bindflag = (uchar_t)default_binding_mode; t0.t_cpupart = &cp_default; t0.t_clfuncs = &sys_classfuncs.thread; t0.t_copyops = NULL; |