10.07.2015 Views

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

186 APPENDIX D. READ-COPY UPDATE IMPLEMENTATIONSCPU 0 CPU 1 CPU 2 CPU 31 i0=srcu_read_lock(&s1) i3=srcu_read_lock(&s2)2 synchronize_srcu(&s1) enter3 i2=srcu_read_lock(&s1)4 srcu_read_unlock(&s1,i0)5 synchronize_srcu(&s1) exit6 srcu_read_unlock(&s1,i2)Table D.1: SRCU Update and Read-Side Critical Sectionsand therefore must not enter the SRCU read-sidecritical section, so we return -EINVAL instead. Onthe other hand, if we are not yet cleaning up, weproceed into the SRCU read-side critical section.Thecleanup() function first sets thenomoresrcuvariable on line 19, but then must wait for allcurrently executing RCU read-side critical sectionsto complete via the synchronize_rcu() primitiveon line 20. Once the cleanup() function reachesline 21, all calls to readside() that could possiblyhave seen nomorersrcu equal to zero must have alreadyreached line 11, and therefore already musthave entered their SRCU read-side critical section.All future calls to readside() will exit via line 8,and will thus refrain from entering the read-side criticalsection.Therefore, once cleanup() completes its call tosynchronize_srcu() on line 21, all SRCU read-sidecritical sections will have completed, and no newones will be able to start. <strong>It</strong> is therefore safe online 22 to call cleanup_srcu_struct() to clean up.D.1.3 ImplementationThis section describes SRCU’s data structures, initializationand cleanup primitives, read-side primitives,and update-side primitives.D.1.3.1 Data StructuresSRCU’s data structures are shown in Figure D.4,and are depicted schematically in Figure D.5. Thecompleted field is a count of the number of graceperiods since the struct srcu was initialized, andas shown in the diagram, its low-order bit is usedto index the struct srcu_struct_array. The per_cpu_reffieldpointstothearray, andthemutexfieldis used to permit but one synchronize_srcu() at atime to proceed.D.1.3.2 Initialization ImplementationSRCU’s initialization function, init_srcu_struct(), is shown in Figure D.6. This functionsimply initializes the fields in the struct1 struct srcu_struct_array {2 int c[2];3 };4 struct srcu_struct {5 int completed;6 struct srcu_struct_array *per_cpu_ref;7 struct mutex mutex;8 };Figure D.4: SRCU Data Structuresstruct srcu_structcompletedper_cpu_refmutexstruct srcu_struct_arrayCPU #0123Low−Order Bit}GP ctr LSB0 1# ## ## ## #Figure D.5: SRCU Data-Structure Diagramsrcu_struct, returning zero if initializationsucceeds or -ENOMEM otherwise.1 int init_srcu_struct(struct srcu_struct *sp)2 {3 sp->completed = 0;4 mutex_init(&sp->mutex);5 sp->per_cpu_ref =6 alloc_percpu(struct srcu_struct_array);7 return (sp->per_cpu_ref ? 0 : -ENOMEM);8 }Figure D.6: SRCU InitializationSRCU’s cleanup functions are shown in FigureD.7. The main cleanup function, cleanup_srcu_struct()isshownonlines19-29ofthisfigure,however, it immediately invokes srcu_readers_active(), shown on lines 13-17 of this figure, toverify that there are no readers currently using thisstruct srcu_struct.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!