Changeset 10954 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 29, 2008 7:51:36 PM (16 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 7 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r10949 r10954 1132 1132 1133 1133 ifdef VBOX_WITH_SOLARIS_VBI 1134 ## @todo svn copy r0drv/solaris/mpnotification-r0drv-solaris.c r0drv/solaris/vbi/mpnotification-r0drv-solaris.c1135 # and change the first file below.1136 1134 RuntimeR0Drv_SOURCES.solaris += \ 1137 r0drv/solaris/ mpnotification-r0drv-solaris.c \1135 r0drv/solaris/vbi/mpnotification-r0drv-solaris.c \ 1138 1136 r0drv/solaris/vbi/alloc-r0drv-solaris.c \ 1139 1137 r0drv/solaris/vbi/assert-r0drv-solaris.c \ -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/os/vbi.c
r9173 r10954 24 24 */ 25 25 26 #pragma ident " @(#)vbi.c 1.1 08/05/26SMI"26 #pragma ident "%Z%%M% %I% %E% SMI" 27 27 28 28 /* … … 78 78 #pragma weak cpuset_all 79 79 #pragma weak cpuset_all_but 80 #pragma weak cpuset_only 80 81 81 82 static struct modlmisc vbi_modlmisc = { … … 159 160 void *ptr; 160 161 161 if ((size >> MMU_PAGESHIFT) << MMU_PAGESHIFT != size)162 if ((size & MMU_PAGEOFFSET) != 0) 162 163 return (NULL); 163 164 … … 428 429 * hack for a kernel compiled with the different NCPU than this module 429 430 */ 431 ASSERT(curthread->t_preempt >= 1); 430 432 if (use_old_xc_call) { 431 433 hack_set = 0; 432 434 for (i = 0; i < ncpus; ++i) 433 hack_set |= 1 << i;435 hack_set |= 1ul << i; 434 436 p_xc_call((xc_arg_t)arg, 0, 0, X_CALL_HIPRI, hack_set, 435 437 (xc_func_t)func); … … 451 453 * hack for a kernel compiled with the different NCPU than this module 452 454 */ 455 ASSERT(curthread->t_preempt >= 1); 453 456 if (use_old_xc_call) { 454 457 hack_set = 0; 455 458 for (i = 0; i < ncpus; ++i) { 456 459 if (i != CPU->cpu_id) 457 hack_set |= 1 << i;460 hack_set |= 1ul << i; 458 461 } 459 462 p_xc_call((xc_arg_t)arg, 0, 0, X_CALL_HIPRI, hack_set, … … 475 478 * hack for a kernel compiled with the different NCPU than this module 476 479 */ 480 ASSERT(curthread->t_preempt >= 1); 477 481 if (use_old_xc_call) { 478 hack_set = 1 << c;482 hack_set = 1ul << c; 479 483 p_xc_call((xc_arg_t)arg, 0, 0, X_CALL_HIPRI, hack_set, 480 484 (xc_func_t)func); 481 485 } else { 482 CPUSET_ ALL_BUT(set, c);486 CPUSET_ONLY(set, c); 483 487 xc_call((xc_arg_t)arg, 0, 0, X_CALL_HIPRI, set, 484 488 (xc_func_t)func); … … 821 825 822 826 /* 823 * This is revision 1of the interface. As more functions are added,827 * This is revision 2 of the interface. As more functions are added, 824 828 * they should go after this point in the file and the revision level 825 829 * increased. 826 830 */ 827 uint_t vbi_revision_level = 1; 831 uint_t vbi_revision_level = 2; 832 833 struct vbi_cpu_watch { 834 void (*vbi_cpu_func)(); 835 void *vbi_cpu_arg; 836 }; 837 838 static int 839 vbi_watcher(cpu_setup_t state, int cpu, void *arg) 840 { 841 vbi_cpu_watch_t *w = arg; 842 int online; 843 844 if (state == CPU_ON) 845 online = 1; 846 else if (state == CPU_OFF) 847 online = 0; 848 else 849 return (0); 850 w->vbi_cpu_func(w->vbi_cpu_arg, cpu, online); 851 return (0); 852 } 853 854 vbi_cpu_watch_t * 855 vbi_watch_cpus(void (*func)(), void *arg, int current_too) 856 { 857 int c; 858 vbi_cpu_watch_t *w; 859 860 w = kmem_alloc(sizeof (*w), KM_SLEEP); 861 w->vbi_cpu_func = func; 862 w->vbi_cpu_arg = arg; 863 mutex_enter(&cpu_lock); 864 register_cpu_setup_func(vbi_watcher, w); 865 if (current_too) { 866 for (c = 0; c < ncpus; ++c) { 867 if (cpu_is_online(cpu[c])) 868 func(arg, c, 1); 869 } 870 } 871 mutex_exit(&cpu_lock); 872 return (w); 873 } 874 875 void 876 vbi_ignore_cpus(vbi_cpu_watch_t *w) 877 { 878 mutex_enter(&cpu_lock); 879 unregister_cpu_setup_func(vbi_watcher, w); 880 mutex_exit(&cpu_lock); 881 kmem_free(w, sizeof (*w)); 882 } 883 884 /* 885 * Simple timers are pretty much a pass through to the cyclic subsystem. 886 */ 887 struct vbi_stimer { 888 cyc_handler_t s_handler; 889 cyc_time_t s_fire_time; 890 cyclic_id_t s_cyclic; 891 uint64_t s_tick; 892 void (*s_func)(void *, uint64_t); 893 void *s_arg; 894 }; 895 896 static void 897 vbi_stimer_func(void *arg) 898 { 899 vbi_stimer_t *t = arg; 900 t->s_func(t->s_arg, t->s_tick++); 901 } 902 903 extern vbi_stimer_t * 904 vbi_stimer_begin( 905 void (*func)(void *, uint64_t), 906 void *arg, 907 uint64_t when, 908 uint64_t interval, 909 int on_cpu) 910 { 911 vbi_stimer_t *t = kmem_zalloc(sizeof (*t), KM_SLEEP); 912 913 ASSERT(when < INT64_MAX); 914 ASSERT(interval < INT64_MAX); 915 ASSERT(interval + when < INT64_MAX); 916 917 t->s_handler.cyh_func = vbi_stimer_func; 918 t->s_handler.cyh_arg = t; 919 t->s_handler.cyh_level = CY_LOCK_LEVEL; 920 t->s_tick = 0; 921 t->s_func = func; 922 t->s_arg = arg; 923 924 mutex_enter(&cpu_lock); 925 if (on_cpu != VBI_ANY_CPU && !vbi_cpu_online(on_cpu)) { 926 t = NULL; 927 goto done; 928 } 929 930 when += gethrtime(); 931 t->s_fire_time.cyt_when = when; 932 if (interval == 0) 933 t->s_fire_time.cyt_interval = INT64_MAX - when; 934 else 935 t->s_fire_time.cyt_interval = interval; 936 t->s_cyclic = cyclic_add(&t->s_handler, &t->s_fire_time); 937 if (on_cpu != VBI_ANY_CPU) 938 cyclic_bind(t->s_cyclic, cpu[on_cpu], NULL); 939 done: 940 mutex_exit(&cpu_lock); 941 return (t); 942 } 943 944 extern void 945 vbi_stimer_end(vbi_stimer_t *t) 946 { 947 ASSERT(t->s_cyclic != CYCLIC_NONE); 948 mutex_enter(&cpu_lock); 949 cyclic_remove(t->s_cyclic); 950 mutex_exit(&cpu_lock); 951 kmem_free(t, sizeof (*t)); 952 } 953 954 /* 955 * Global timers are more complicated. They include a counter on the callback, 956 * that indicates the first call on a given cpu. 957 */ 958 struct vbi_gtimer { 959 uint64_t *g_counters; 960 void (*g_func)(void *, uint64_t); 961 void *g_arg; 962 uint64_t g_when; 963 uint64_t g_interval; 964 cyclic_id_t g_cyclic; 965 }; 966 967 static void 968 vbi_gtimer_func(void *arg) 969 { 970 vbi_gtimer_t *t = arg; 971 t->g_func(t->g_arg, t->g_counters[CPU->cpu_id]); 972 } 973 974 /* 975 * Whenever a cpu is onlined, need to reset the g_counters[] for it to zero. 976 */ 977 static void 978 vbi_gtimer_online(void *arg, cpu_t *cpu, cyc_handler_t *h, cyc_time_t *ct) 979 { 980 vbi_gtimer_t *t = arg; 981 hrtime_t now; 982 983 t->g_counters[cpu->cpu_id] = 0; 984 h->cyh_func = vbi_gtimer_func; 985 h->cyh_arg = t; 986 h->cyh_level = CY_LOCK_LEVEL; 987 now = gethrtime(); 988 if (t->g_when < now) 989 ct->cyt_when = now + t->g_interval / 2; 990 else 991 ct->cyt_when = t->g_when; 992 ct->cyt_interval = t->g_interval; 993 } 994 995 996 vbi_gtimer_t * 997 vbi_gtimer_begin( 998 void (*func)(void *, uint64_t), 999 void *arg, 1000 uint64_t when, 1001 uint64_t interval) 1002 { 1003 vbi_gtimer_t *t; 1004 cyc_omni_handler_t omni; 1005 1006 /* 1007 * one shot global timer is not supported yet. 1008 */ 1009 if (interval == 0) 1010 return (NULL); 1011 1012 ASSERT(when < INT64_MAX); 1013 ASSERT(interval < INT64_MAX); 1014 ASSERT(interval + when < INT64_MAX); 1015 1016 t = kmem_zalloc(sizeof (*t), KM_SLEEP); 1017 t->g_counters = kmem_zalloc(ncpus * sizeof (uint64_t), KM_SLEEP); 1018 t->g_when = when + gethrtime(); 1019 t->g_interval = interval; 1020 t->g_arg = arg; 1021 t->g_func = func; 1022 t->g_cyclic = CYCLIC_NONE; 1023 1024 omni.cyo_online = (void (*)())vbi_gtimer_online; 1025 omni.cyo_offline = NULL; 1026 omni.cyo_arg = t; 1027 1028 mutex_enter(&cpu_lock); 1029 t->g_cyclic = cyclic_add_omni(&omni); 1030 mutex_exit(&cpu_lock); 1031 return (t); 1032 } 1033 1034 extern void 1035 vbi_gtimer_end(vbi_gtimer_t *t) 1036 { 1037 ASSERT(t->g_cyclic != CYCLIC_NONE); 1038 mutex_enter(&cpu_lock); 1039 cyclic_remove(t->g_cyclic); 1040 mutex_exit(&cpu_lock); 1041 kmem_free(t->g_counters, ncpus * sizeof (uint64_t)); 1042 kmem_free(t, sizeof (*t)); 1043 } -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/sys/vbi.h
r9173 r10954 28 28 #define _SYS_VBI_H 29 29 30 #pragma ident " @(#)vbi.h 1.1 08/05/26SMI"30 #pragma ident "%Z%%M% %I% %E% SMI" 31 31 32 32 #ifdef __cplusplus … … 109 109 */ 110 110 extern uint64_t vbi_timer_granularity(void); 111 112 /* old timer funcs */ 111 113 extern void *vbi_timer_create(void *callback, void *arg1, void *arg2, 112 114 uint64_t interval); … … 222 224 extern uint_t vbi_revision_level; 223 225 226 /* begin interfaces defined for version 2 */ 227 228 /* 229 * Install/remove a call back for CPU online/offline event notification. 230 * 231 * The call back func is invoked with 3 arguments: 232 * void func(void *arg, int cpu, int online); 233 * - arg is passed through from vbi_watch_cpus() 234 * - cpu is the CPU id involved 235 * - online is non-zero for a CPU that comes online and 0 for a CPU that is 236 * going offline. 237 * 238 * If current_too is non-zero, then a cpu online event will be invoked for all 239 * currently online CPUs. 240 * 241 * Note there is no guarantee about which CPU the function is invoked on. 242 */ 243 typedef struct vbi_cpu_watch vbi_cpu_watch_t; 244 extern vbi_cpu_watch_t *vbi_watch_cpus(void (*func)(), void *arg, 245 int current_too); 246 extern void vbi_ignore_cpus(vbi_cpu_watch_t *); 247 #pragma weak vbi_watch_cpus 248 #pragma weak vbi_ignore_cpus 249 250 /* 251 * New timer interfaces 252 * 253 * A simple timer fires just once and on only one cpu. It may be repeating or 254 * a one shot. 255 * 256 * Support for one shot (ie interval == 0) global timers is optional. 257 * 258 * For simple timers, if cpu is VBI_ANY_CPU, the timer may fire on any 259 * available cpu otherwise the timer will fire only on the given cpu 260 * 261 * The repeating call back, func, is invoked with 2 arguments: 262 * - arg is just passed through 263 * - a uint64_t counter that starts at 0 and increments with each timer event. 264 * The count is per-cpu and resets whenever a cpu goes offline and comes back 265 * online. 266 * 267 * The when parameter is time relative to now. 268 * 269 * vbi_stimer_begin() may return NULL if there was an error in 270 * creating the timer, for example if a requested cpu is not online. 271 * 272 * vbi_gtimer_begin() may return NULL when called if it does not 273 * support the requested kind of timer (ie interval == 0) 274 */ 275 #define VBI_ANY_CPU (-1) 276 277 typedef struct vbi_stimer vbi_stimer_t; 278 extern vbi_stimer_t *vbi_stimer_begin(void (*func)(void *, uint64_t), void *arg, 279 uint64_t when, uint64_t interval, int cpu); 280 extern void vbi_stimer_end(vbi_stimer_t *); 281 #pragma weak vbi_stimer_begin 282 #pragma weak vbi_stimer_end 283 284 typedef struct vbi_gtimer vbi_gtimer_t; 285 extern vbi_gtimer_t *vbi_gtimer_begin(void (*func)(void *, uint64_t), void *arg, 286 uint64_t when, uint64_t interval); 287 extern void vbi_gtimer_end(vbi_gtimer_t *); 288 #pragma weak vbi_gtimer_begin 289 #pragma weak vbi_gtimer_end 290 291 292 /* end of interfaces defined for version 2 */ 293 224 294 #ifdef __cplusplus 225 295 } -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/mp-r0drv-solaris.c
r9429 r10954 229 229 RTCPUID idCpu = RTMpCpuId(); 230 230 231 Assert(idCpu != pArgs->idCpu);231 Assert(idCpu == pArgs->idCpu); 232 232 pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2); 233 233 ASMAtomicIncU32(&pArgs->cHits); -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/mpnotification-r0drv-solaris.c
r10948 r10954 36 36 37 37 #include <iprt/mp.h> 38 #include <iprt/err.h> 38 39 #include "r0drv/mp-r0drv.h" 39 40 40 41 41 static int rtMpNotificationSolarisCallback(cpu_setup_t enmSolarisEvent, int iCpu, void *pvUser)42 static void rtMpNotificationSolarisCallback(void *pvUser, int iCpu, int online) 42 43 { 43 44 NOREF(pvUser); 44 45 45 46 /* ASSUMES iCpu == RTCPUID */ 46 switch (enmSolarisEvent) 47 { 48 case CPU_INIT: 49 case CPU_CONFIG: 50 case CPU_UNCONFIG: 51 break; 52 53 case CPU_ON: 54 rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, iCpu); 55 break; 56 57 case CPU_OFF: 58 rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, iCpu); 59 break; 60 61 case CPU_CPUPART_IN: 62 case CPU_CPUPART_OUT: 63 /** @todo are these relevant? */ 64 break; 65 } 66 return 0; 47 if (online) 48 rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, iCpu); 49 else 50 rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, iCpu); 67 51 } 68 52 53 static vbi_cpu_watch_t *watch_handle = NULL; 69 54 70 55 int rtR0MpNotificationNativeInit(void) 71 56 { 72 register_cpu_setup_func(rtMpNotificationSolarisCallback, NULL); 57 if (vbi_revision_level < 2) 58 return VERR_NOT_SUPPORTED; 59 if (watch_handle != NULL) 60 return VERR_INVALID_PARAMETER; 61 watch_handle = vbi_watch_cpus(rtMpNotificationSolarisCallback, NULL, 0); 62 return VINF_SUCCESS; 73 63 } 74 64 … … 76 66 void rtR0MpNotificationNativeTerm(void) 77 67 { 78 unregister_cpu_setup_func(rtMpNotificationSolarisCallback, NULL); 68 if (vbi_revision_level >= 2 && watch_handle != NULL) 69 vbi_ignore_cpus(watch_handle); 70 watch_handle = NULL; 79 71 } 80 72 -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/timer-r0drv-solaris.c
r9444 r10954 60 60 /** Flag indicating the the timer is suspended. */ 61 61 uint8_t volatile fSuspended; 62 /** Run on all CPUs if set */ 63 uint8_t fAllCpu; 62 64 /** Whether the timer must run on a specific CPU or not. */ 63 65 uint8_t fSpecificCpu; 64 66 /** The CPU it must run on if fSpecificCpu is set. */ 65 67 uint8_t iCpu; 66 /** The Solaris timer handle. */ 67 void *handle; 68 /** The nano second interval for repeating timers */ 69 uint64_t interval; 70 /** simple Solaris timer handle. */ 71 vbi_stimer_t *stimer; 72 /** global Solaris timer handle. */ 73 vbi_gtimer_t *gtimer; 68 74 /** The user callback. */ 69 75 PFNRTTIMER pfnTimer; 70 /** The current tick count. */ 71 uint64_t iTick; 72 76 /** The argument for the user callback. */ 77 void *pvUser; 73 78 } RTTIMER; 74 79 75 80 76 /** 77 * Callback wrapper for adding the new iTick argument. 78 * 79 * @param pTimer The timer. 80 * @param pvUser The user argument. 81 */ 82 static void rtTimerSolarisCallbackWrapper(PRTTIMER pTimer, void *pvUser) 83 { 84 pTimer->pfnTimer(pTimer, pvUser, ++pTimer->iTick); 81 /* 82 * Need a wrapper to get the PRTTIMER passed through 83 */ 84 static void rtTimerSolarisCallbackWrapper(PRTTIMER pTimer, uint64_t tick) 85 { 86 pTimer->pfnTimer(pTimer, pTimer->pvUser, tick); 85 87 } 86 88 … … 97 99 if (!RTTIMER_FLAGS_ARE_VALID(fFlags)) 98 100 return VERR_INVALID_PARAMETER; 101 if (vbi_revision_level < 2) 102 return VERR_NOT_SUPPORTED; 103 99 104 if ( (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 100 /** @todo implement && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL*/) 105 && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL 106 && !RTMpIsCpuPossible((fFlags & RTTIMER_FLAGS_CPU_MASK))) 107 return VERR_CPU_NOT_FOUND; 108 109 if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL && u64NanoInterval == 0) 101 110 return VERR_NOT_SUPPORTED; 102 111 … … 110 119 pTimer->u32Magic = RTTIMER_MAGIC; 111 120 pTimer->fSuspended = true; 112 pTimer->fSpecificCpu = !!(fFlags & RTTIMER_FLAGS_CPU_SPECIFIC); 113 pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; 114 pTimer->handle = vbi_timer_create(rtTimerSolarisCallbackWrapper, pTimer, pvUser, u64NanoInterval); 121 if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL) 122 { 123 pTimer->fAllCpu = true; 124 pTimer->fSpecificCpu = false; 125 } 126 else if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) 127 { 128 pTimer->fAllCpu = false; 129 pTimer->fSpecificCpu = true; 130 pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; 131 } 132 pTimer->interval = u64NanoInterval; 115 133 pTimer->pfnTimer = pfnTimer; 116 pTimer->iTick = 0; 134 pTimer->pvUser = pvUser; 135 pTimer->stimer = NULL; 136 pTimer->gtimer = NULL; 117 137 118 138 *ppTimer = pTimer; … … 145 165 * Free the associated resources. 146 166 */ 167 RTTimerStop(pTimer); 147 168 pTimer->u32Magic++; 148 vbi_timer_stop(pTimer->handle);149 vbi_timer_destroy(pTimer->handle);150 169 RTMemFree(pTimer); 151 170 return VINF_SUCCESS; … … 155 174 RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First) 156 175 { 176 int cpu = VBI_ANY_CPU; 177 157 178 if (!rtTimerIsValid(pTimer)) 158 179 return VERR_INVALID_HANDLE; … … 160 181 return VERR_TIMER_ACTIVE; 161 182 162 /*163 * Calc when it should start firing.164 */165 183 pTimer->fSuspended = false; 166 vbi_timer_start(pTimer->handle, u64First); 184 if (pTimer->fAllCpu) 185 { 186 pTimer->gtimer = vbi_gtimer_begin(rtTimerSolarisCallbackWrapper, pTimer, u64First, pTimer->interval); 187 if (pTimer->gtimer == NULL) 188 return VERR_INVALID_PARAMETER; 189 } 190 else 191 { 192 if (pTimer->fSpecificCpu) 193 cpu = pTimer->iCpu; 194 pTimer->stimer = vbi_stimer_begin(rtTimerSolarisCallbackWrapper, pTimer, u64First, pTimer->interval, cpu); 195 if (pTimer->stimer == NULL) 196 { 197 if (cpu != VBI_ANY_CPU) 198 return VERR_CPU_OFFLINE; 199 return VERR_INVALID_PARAMETER; 200 } 201 } 167 202 168 203 return VINF_SUCCESS; … … 177 212 return VERR_TIMER_SUSPENDED; 178 213 179 /*180 * Suspend the timer.181 */182 214 pTimer->fSuspended = true; 183 vbi_timer_stop(pTimer->handle); 215 if (pTimer->stimer) 216 { 217 vbi_stimer_end(pTimer->stimer); 218 pTimer->stimer = NULL; 219 } 220 else if (pTimer->gtimer) 221 { 222 vbi_gtimer_end(pTimer->gtimer); 223 pTimer->gtimer = NULL; 224 } 184 225 185 226 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.