| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: linux_reservation.c,v 1.5 2018/08/27 14:13:00 riastradh Exp $ */ | | 1 | /* $NetBSD: linux_reservation.c,v 1.6 2018/08/27 14:13:46 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2018 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Taylor R. Campbell. | | 8 | * by Taylor R. Campbell. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,27 +20,27 @@ | | | @@ -20,27 +20,27 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.5 2018/08/27 14:13:00 riastradh Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: linux_reservation.c,v 1.6 2018/08/27 14:13:46 riastradh Exp $"); |
34 | | | 34 | |
35 | #include <linux/fence.h> | | 35 | #include <linux/fence.h> |
36 | #include <linux/reservation.h> | | 36 | #include <linux/reservation.h> |
37 | | | 37 | |
38 | DEFINE_WW_CLASS(reservation_ww_class __cacheline_aligned); | | 38 | DEFINE_WW_CLASS(reservation_ww_class __cacheline_aligned); |
39 | | | 39 | |
40 | static struct reservation_object_list * | | 40 | static struct reservation_object_list * |
41 | objlist_tryalloc(uint32_t n) | | 41 | objlist_tryalloc(uint32_t n) |
42 | { | | 42 | { |
43 | struct reservation_object_list *list; | | 43 | struct reservation_object_list *list; |
44 | | | 44 | |
45 | list = kmem_alloc(offsetof(typeof(*list), shared[n]), KM_NOSLEEP); | | 45 | list = kmem_alloc(offsetof(typeof(*list), shared[n]), KM_NOSLEEP); |
46 | if (list == NULL) | | 46 | if (list == NULL) |
| @@ -401,63 +401,66 @@ reservation_object_add_shared_fence(stru | | | @@ -401,63 +401,66 @@ reservation_object_add_shared_fence(stru |
401 | replace = list->shared[i]; | | 401 | replace = list->shared[i]; |
402 | list->shared[i] = fence; | | 402 | list->shared[i] = fence; |
403 | break; | | 403 | break; |
404 | } | | 404 | } |
405 | } | | 405 | } |
406 | | | 406 | |
407 | /* If we didn't find one, add it at the end. */ | | 407 | /* If we didn't find one, add it at the end. */ |
408 | if (i == list->shared_count) | | 408 | if (i == list->shared_count) |
409 | list->shared[list->shared_count++] = fence; | | 409 | list->shared[list->shared_count++] = fence; |
410 | | | 410 | |
411 | /* Commit the update. */ | | 411 | /* Commit the update. */ |
412 | reservation_object_write_commit(robj, &ticket); | | 412 | reservation_object_write_commit(robj, &ticket); |
413 | } else { | | 413 | } else { |
414 | KASSERT(list->shared_count < prealloc->shared_max); | | 414 | uint32_t shared_count = (list == NULL? 0 : list->shared_count); |
| | | 415 | |
| | | 416 | KASSERT(shared_count < prealloc->shared_max); |
415 | | | 417 | |
416 | /* | | 418 | /* |
417 | * Copy the fences over, but replace if we find one | | 419 | * Copy the fences over, but replace if we find one |
418 | * with the same context number. | | 420 | * with the same context number. |
419 | */ | | 421 | */ |
420 | for (i = 0; i < list->shared_count; i++) { | | 422 | for (i = 0; i < shared_count; i++) { |
421 | if (replace == NULL && | | 423 | if (replace == NULL && |
422 | list->shared[i]->context == fence->context) { | | 424 | list->shared[i]->context == fence->context) { |
423 | replace = list->shared[i]; | | 425 | replace = list->shared[i]; |
424 | prealloc->shared[i] = fence; | | 426 | prealloc->shared[i] = fence; |
425 | } else { | | 427 | } else { |
426 | prealloc->shared[i] = list->shared[i]; | | 428 | prealloc->shared[i] = list->shared[i]; |
427 | } | | 429 | } |
428 | } | | 430 | } |
429 | prealloc->shared_count = list->shared_count; | | 431 | prealloc->shared_count = shared_count; |
430 | | | 432 | |
431 | /* If we didn't find one, add it at the end. */ | | 433 | /* If we didn't find one, add it at the end. */ |
432 | if (replace == NULL) | | 434 | if (replace == NULL) |
433 | prealloc->shared[prealloc->shared_count++] = fence; | | 435 | prealloc->shared[prealloc->shared_count++] = fence; |
434 | | | 436 | |
435 | /* Now ready to replace the list. Begin an update. */ | | 437 | /* Now ready to replace the list. Begin an update. */ |
436 | reservation_object_write_begin(robj, &ticket); | | 438 | reservation_object_write_begin(robj, &ticket); |
437 | | | 439 | |
438 | /* Replace the list. */ | | 440 | /* Replace the list. */ |
439 | robj->robj_list = prealloc; | | 441 | robj->robj_list = prealloc; |
440 | robj->robj_prealloc = NULL; | | 442 | robj->robj_prealloc = NULL; |
441 | | | 443 | |
442 | /* Commit the update. */ | | 444 | /* Commit the update. */ |
443 | reservation_object_write_commit(robj, &ticket); | | 445 | reservation_object_write_commit(robj, &ticket); |
444 | | | 446 | |
445 | /* | | 447 | /* |
446 | * Free the old list when it is convenient. (We are | | 448 | * If there is an old list, free it when convenient. |
447 | * not in a position at this point to sleep waiting for | | 449 | * (We are not in a position at this point to sleep |
448 | * activity on all CPUs.) | | 450 | * waiting for activity on all CPUs.) |
449 | */ | | 451 | */ |
450 | objlist_defer_free(list); | | 452 | if (list != NULL) |
| | | 453 | objlist_defer_free(list); |
451 | } | | 454 | } |
452 | | | 455 | |
453 | /* Release a fence if we replaced it. */ | | 456 | /* Release a fence if we replaced it. */ |
454 | if (replace) | | 457 | if (replace) |
455 | fence_put(replace); | | 458 | fence_put(replace); |
456 | } | | 459 | } |
457 | | | 460 | |
458 | int | | 461 | int |
459 | reservation_object_get_fences_rcu(struct reservation_object *robj, | | 462 | reservation_object_get_fences_rcu(struct reservation_object *robj, |
460 | struct fence **fencep, unsigned *nsharedp, struct fence ***sharedp) | | 463 | struct fence **fencep, unsigned *nsharedp, struct fence ***sharedp) |
461 | { | | 464 | { |
462 | struct reservation_object_list *list; | | 465 | struct reservation_object_list *list; |
463 | struct fence *fence; | | 466 | struct fence *fence; |