Merge commit '37e84ab74e939caf52150fc3352081786ecc0c29' into merges
[unleashed.git] / usr / src / uts / common / io / usb / clients / usbser / usbser_rseq.c
blob0c9c368961345a5aa982b18d18bf28b73b10b9f3
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * rseq implementation
31 #include <sys/usb/clients/usbser/usbser_rseq.h>
33 #ifdef _KERNEL
34 #include <sys/debug.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 /*LINTED E_STATIC_UNUSED*/
38 static long rseq_random() __unused;
39 #define random rseq_random
40 #else
41 #include <assert.h>
42 #define ASSERT assert
43 #include <stdlib.h>
44 #endif
47 /*ARGSUSED*/
48 static int
49 rseq_do_common(rseq_t *rseq, int num, uintptr_t arg, int flags, int fail_err,
50 uintptr_t fail_num)
52 int i;
53 rseq_step_t *s;
54 int rval = RSEQ_OK;
56 for (i = 0; i < num; i++) {
57 s = &rseq[i].r_do;
59 if (s->s_func == NULL) {
60 continue;
62 s->s_rval = (i != fail_num) ? s->s_func(arg) : fail_err;
63 rval = (s->s_cb) ? (s->s_cb(rseq, i, arg)) : RSEQ_OK;
65 if (rval == RSEQ_UNDO) {
66 (void) rseq_undo(rseq, i, arg, flags);
67 break;
68 } else if (rval == RSEQ_ABORT) {
69 break;
71 ASSERT(rval == RSEQ_OK);
73 return (rval);
77 /*ARGSUSED*/
78 static int
79 rseq_undo_common(rseq_t *rseq, int num, uintptr_t arg, int flags, int fail_err,
80 uintptr_t fail_num)
82 int i;
83 rseq_step_t *s;
84 int rval = RSEQ_OK;
86 for (i = num - 1; i >= 0; i--) {
87 s = &rseq[i].r_undo;
89 if (s->s_func == NULL) {
90 continue;
92 s->s_rval = (i != fail_num) ? s->s_func(arg) : fail_err;
93 rval = (s->s_cb) ? (s->s_cb(rseq, i, arg)) : RSEQ_OK;
95 if (rval == RSEQ_ABORT) {
96 break;
98 ASSERT(rval == RSEQ_OK);
100 return (rval);
105 rseq_do(rseq_t *rseq, int num, uintptr_t arg, int flags)
107 return (rseq_do_common(rseq, num, arg, flags, 0, -1));
112 rseq_undo(rseq_t *rseq, int num, uintptr_t arg, int flags)
114 return (rseq_undo_common(rseq, num, arg, flags, 0, -1));
117 #ifdef DEBUG
119 #ifndef __lock_lint
121 static int
122 rseq_debug(rseq_t *rseq, int num, uintptr_t arg, int flags, int scenario,
123 uintptr_t sarg1, uintptr_t sarg2,
124 int (*func)(rseq_t *, int, uintptr_t, int, int, uintptr_t))
126 int rnd, rval = RSEQ_OK, i;
128 switch (scenario) {
129 case RSEQ_DBG_FAIL_ONE:
130 rval = func(rseq, num, arg, flags, sarg1, sarg2);
131 break;
132 case RSEQ_DBG_FAIL_ONE_RANDOM:
133 rnd = random() % num;
134 rval = func(rseq, num, arg, flags, sarg1, rnd);
135 break;
136 case RSEQ_DBG_FAIL_ONEBYONE:
137 for (i = 0; i < num; i++) {
138 rval = func(rseq, num, arg, flags, sarg1, i);
140 * when aborted, the undo path is not executed, so we
141 * can't continue without the risk of resource leakage.
143 if (rval == RSEQ_ABORT) {
144 break;
147 break;
148 default:
149 ASSERT(!"rseq_debug: incorrect debug scenario");
150 rval = RSEQ_ABORT;
152 return (rval);
157 rseq_do_debug(rseq_t *rseq, int num, uintptr_t arg, int flags, int scenario,
158 uintptr_t sarg1, uintptr_t sarg2)
160 return (rseq_debug(rseq, num, arg, flags, scenario, sarg1, sarg2,
161 rseq_do_common));
166 rseq_undo_debug(rseq_t *rseq, int num, uintptr_t arg, int flags, int scenario,
167 uintptr_t sarg1, uintptr_t sarg2)
169 return (rseq_debug(rseq, num, arg, flags, scenario, sarg1, sarg2,
170 rseq_undo_common));
173 #endif /* __lock_lint */
175 #endif /* DEBUG */
177 #ifdef _KERNEL
178 static long
179 rseq_random()
181 return (ddi_get_lbolt());
183 #endif /* _KERNEL */