atomicadd(int* address, int val); float atomicadd(float* address, float val); atomicsub(int* address, int val); atomicexch(int* address, int val);

Similar documents
Fine-Grained Synchronization and Lock-Free Programming

Fine-grained synchronization & lock-free programming

Fine-grained synchronization & lock-free data structures

Atomic Operations. Atomic operations, fast reduction. GPU Programming. Szénási Sándor.

Chapter 9 STACK, QUEUE

Part 1 Fine-grained Operations

CS 134: Operating Systems

CUDA Odds and Ends. Joseph Kider University of Pennsylvania CIS Fall 2011

CUDA Odds and Ends. Administrivia. Administrivia. Agenda. Patrick Cozzi University of Pennsylvania CIS Spring Assignment 5.

Transactional Memory. Lecture 18: Parallel Computer Architecture and Programming CMU /15-618, Spring 2017

COL106: Data Structures and Algorithms. Ragesh Jaiswal, IIT Delhi

Intermediate Programming, Spring 2017*

Concurrency: Mutual Exclusion (Locks)

The combination of pointers, structs, and dynamic memory allocation allow for creation of data structures

Stack & Queue on Self-Referencing Structures

Lecture Notes CPSC 122 (Fall 2014) Today Quiz 7 Doubly Linked Lists (Unsorted) List ADT Assignments Program 8 and Reading 6 out S.

CS32 Discussion Week 3

CS 179: GPU Programming LECTURE 5: GPU COMPUTE ARCHITECTURE FOR THE LAST TIME

Queues. A queue is a special type of structure that can be used to maintain data in an organized way.

INTERFACING REAL-TIME AUDIO AND FILE I/O

Stack & Queue on Self-Referencing Structures

C++ - Lesson 2 This is a function prototype. a' is a function that takes an integer array argument and returns an integer pointer.

CS 241 Honors Concurrent Data Structures

CS132 Algorithm. Instructor: Jialiang Lu Office: Information Center 703

30. Parallel Programming IV

Stack. 4. In Stack all Operations such as Insertion and Deletion are permitted at only one end. Size of the Stack 6. Maximum Value of Stack Top 5

Outline. Example stack Version 1 -- int stack with fixed array Version 2 -- int stack with flexible array Version 3 -- with interface

CS32 - Week 2. Umut Oztok. July 1, Umut Oztok CS32 - Week 2

MCS 360 Exam 2 11 November In order to get full credit, you need to show your work.

Midterm Review. CS 211 Fall 2018

Distributed Operating Systems

Solution for Data Structure

Final Exam. 11 May 2018, 120 minutes, 26 questions, 100 points

Introduction to CUDA (2 of 2)

(6-1) Basics of a Queue. Instructor - Andrew S. O Fallon CptS 122 (September 26, 2018) Washington State University

Overview of today s lecture. Quick recap of previous C lectures. Introduction to C programming, lecture 2. Abstract data type - Stack example

Linear Structures. Linear Structure. Implementations. Array details. List details. Operations 4/18/2013

FORTH SEMESTER DIPLOMA EXAMINATION IN ENGINEERING/ TECHNOLIGY- OCTOBER, 2012 DATA STRUCTURE

Data Structures. Jia-Liang Lu. Slides based on the course notes of C.A. Shaffer

Homework Assignment #1

Marwan Burelle. Parallel and Concurrent Programming

CSE 143. Linked Lists. Linked Lists. Manipulating Nodes (1) Creating Nodes. Manipulating Nodes (3) Manipulating Nodes (2) CSE 143 1

Linear Structures. Linear Structure. Implementations. Array details. List details. Operations 2/10/2013

CprE 288 Introduction to Embedded Systems Exam 1 Review. 1

Stanford University Computer Science Department CS 140 Midterm Exam Dawson Engler Winter 1999

l Determine if a number is odd or even l Determine if a number/character is in a range - 1 to 10 (inclusive) - between a and z (inclusive)

Garbage Collection. Vyacheslav Egorov

Linked List using a Sentinel

11 'e' 'x' 'e' 'm' 'p' 'l' 'i' 'f' 'i' 'e' 'd' bool equal(const unsigned char pstr[], const char *cstr) {

19-Nov CSCI 2132 Software Development Lecture 29: Linked Lists. Faculty of Computer Science, Dalhousie University Heap (Free Store)

Order Is A Lie. Are you sure you know how your code runs?

Pointers. A pointer value is the address of the first byte of the pointed object in the memory. A pointer does not know how many bytes it points to.

Queues. October 20, 2017 Hassan Khosravi / Geoffrey Tien 1

Chapter 5. Binary Trees

Chapter 8 STRUCTURES IN C

CS 537 Lecture 11 Locks

list<t>::const_iterator it1 = lst.begin(); // points to first element list<t>::const_iterator it2 = lst.begin(); // points to second element it2++;

15-418/618, Spring Exam 2 Practice SOLUTIONS

Introduction to Lock-Free Algorithms

Lecture 9: Multiprocessor OSs & Synchronization. CSC 469H1F Fall 2006 Angela Demke Brown

CROWDMARK. Examination Midterm. Spring 2017 CS 350. Closed Book. Page 1 of 30. University of Waterloo CS350 Midterm Examination.

Distributed Systems Synchronization. Marcus Völp 2007

CS 261: Data Structures. Dynamic Array Queue

CMPT 125: Practice Midterm Answer Key

Lesson 8: Linked List Deque

Concurrency: Locks. Announcements

CS 261: Data Structures. Dynamic Array Queue

Stanford CS149: Parallel Computing Written Assignment 3

Pointers, Dynamic Data, and Reference Types

Final Exam. 12 December 2018, 120 minutes, 26 questions, 100 points

CMSC421: Principles of Operating Systems

Come to the PASS workshop with your mock exam complete. During the workshop you can work with other students to review your work.

Fall, 2015 Prof. Jungkeun Park

Midterm I Exam Principles of Imperative Computation Frank Pfenning. February 17, 2011

Advanced Systems Programming

CS5460/6460: Operating Systems. Lecture 11: Locking. Anton Burtsev February, 2014

Linked Lists. Data and File Structures Laboratory. DFS Lab (ISI) Linked Lists 1 / 12

Dynamic Data Structures

Deductive Verification of Data Structures

Lecture 8 Dynamic Memory Allocation

Reference Counting. Reference counting: a way to know whether a record has other users

CSCE 2014 Final Exam Spring Version A

Abstract Data Types and Stacks

Structured Data. CIS 15 : Spring 2007

Actually, C provides another type of variable which allows us to do just that. These are called dynamic variables.

Lecture 19: Synchronization. CMU : Parallel Computer Architecture and Programming (Spring 2012)

Lindsay Groves, Simon Doherty. Mark Moir, Victor Luchangco

An application: foreign function bindings

Chapter 20: Binary Trees

More about BOOLEAN issues

Part 1: Concepts and Hardware- Based Approaches

LOCKLESS ALGORITHMS. Lockless Algorithms. CAS based algorithms stack order linked list

Basic program The following is a basic program in C++; Basic C++ Source Code Compiler Object Code Linker (with libraries) Executable

Chapter 19: Program Design. Chapter 19. Program Design. Copyright 2008 W. W. Norton & Company. All rights reserved.

Computer Science Foundation Exam

Programming Languages

GPU programming basics. Prof. Marco Bertini

malloc(), calloc(), realloc(), and free()

CS558 Programming Languages

Model Solution for QP CODE : ( 3 Hours )

Transcription:

int atomicadd(int* address, int val); float atomicadd(float* address, float val); int int atomicsub(int* address, int val); atomicexch(int* address, int val); float atomicexch(float* address, float val); int int atomicmin(int* address, int val); atomicmax(int* address, int val); unsigned int atomicinc(unsigned int* address, unsigned int val); unsigned int atomicdec(unsigned int* address, unsigned int val); int int atomiccas(int* address, int compare, int val); atomicand(int* address, int val); // bitwise int atomicor(int* address, int val); // bitwise int atomicxor(int* address, int val); // bitwise

// atomiccas: // atomic compare and swap performs this logic atomically int atomiccas(int* addr, int compare, int val) { int old = *addr; *addr = (old == compare)? val : old; return old; void atomic_min(int* addr, int x) { int old = *addr; int new = min(old, x); while (atomiccas(addr, old, new)!= old) { old = *addr; new = min(old, x); int atomic_increment(int* addr, int x); void lock(int* addr); // for signed values of x

atomic<int> i; i++; // atomically increment i int a = i; // do stuff i.compare_exchange_strong(a, 10); // if i has same value as a, set i to 10 bool b = i.is_lock_free(); // true if implementation of atomicity // is lock free

struct Node { int value; Node* next; ; struct List { Node* head; ; void insert(list* list, int value) { Node* n = new Node; n->value = value; // assume case of inserting before head of // of list is handled here (to keep slide simple) Node* prev = list->head; Node* cur = list->head->next; while (cur) { if (cur->value > value) break; void delete(list* list, int value) { // assume case of deleting first element is // handled here (to keep slide simple) Node* prev = list->head; Node* cur = list->head->next; while (cur) { if (cur->value == value) { prev->next = cur->next; delete cur; return; prev = cur; cur = cur->next; n->next = cur; prev->next = n; prev = cur; cur = cur->next;

3 5 10 11 18 6 3 5 10 11 18

6 3 5 10 11 18 7 3 5 10 11 18 7 prev->next 3 5 10 11 18

struct Node { int value; Node* next; ; struct List { Node* head; Lock lock; ; void insert(list* list, int value) { Node* n = new Node; n->value = value; lock(list->lock); // assume case of inserting before head of // of list is handled here (to keep slide simple) void delete(list* list, int value) { lock(list->lock); // assume case of deleting first element is // handled here (to keep slide simple) Node* prev = list->head; Node* cur = list->head->next; Node* prev = list->head; Node* cur = list->head->next; while (cur) { if (cur->value > value) break; prev = cur; cur = cur->next; n->next = cur; prev->next = n; unlock(list->lock); while (cur) { if (cur->value == value) { prev->next = cur->next; delete cur; unlock(list->lock); return; prev = cur; cur = cur->next; unlock(list->lock);

struct Node { int value; Node* next; ; struct List { Node* head; ; void insert(list* list, int value) { Node* n = new Node; n->value = value; // assume case of inserting before head of // of list is handled here (to keep slide simple) Node* prev = list->head; Node* cur = list->head->next; while (cur) { if (cur->value > value) break; void delete(list* list, int value) { // assume case of deleting first element is // handled here (to keep slide simple) Node* prev = list->head; Node* cur = list->head->next; while (cur) { if (cur->value == value) { prev->next = cur->next; delete cur; return; prev = cur; cur = cur->next; prev->next = n; n->next = cur; prev = cur; cur = cur->next; 3 5 10 11 18

3 5 10 11 18 T0 T0 T0 T0

3 5 10 11 18 T1 T1 T0 T0

3 5 10 18 T1 T1

3 5 18 T1

struct Node { int value; Node* next; Lock* lock; ; struct List { Node* head; Lock* lock; ; void insert(list* list, int value) { Node* n = new Node; n->value = value; void delete(list* list, int value) { // assume case of delete head handled here // (to keep slide simple) // assume case of insert before head handled // here (to keep slide simple) Node* prev, *cur; lock(list->lock); prev = list->head; cur = list->head->next; lock(prev->lock); unlock(list->lock); if (cur) lock(cur->lock); while (cur) { if (cur->value > value) break; Node* old_prev = prev; prev = cur; cur = cur->next; unlock(old_prev->lock); if (cur) lock(cur->lock); n->next = cur; prev->next = n; unlock(prev->lock); if (cur) unlock(cur->lock); Node* prev, *cur; lock(list->lock); prev = list->head; cur = list->head->next; lock(prev->lock); unlock(list->lock); if (cur) lock(cur->lock) while (cur) { if (cur->value == value) { prev->next = cur->next; unlock(prev->lock); unlock(cur->lock); delete cur; return; Node* old_prev = prev; prev = cur; cur = cur->next; unlock(old_prev->lock); if (cur) lock(cur->lock); unlock(prev->lock);

struct Tree { Node* root; ; struct Node { int value; Node* left; Node* right; ; void insert(tree* tree, int value); void delete(tree* tree, int value);

struct Queue { int data[n]; int head; // head of queue int tail; // next free element ; // return false if queue is full bool push(queue* q, int value) { // queue is full if tail is element before head if (q->tail == MOD_N(q->head - 1)) return false; void init(queue* q) { q->head = q->tail = 0; q.data[q->tail] = value; q->tail = MOD_N(q->tail + 1); return true; // returns false if queue is empty bool pop(queue* q, int* value) { // if not empty if (q->head!= q->tail) { *value = q->data[q->head]; q->head = MOD_N(q->head + 1); return true; return false;

struct Node { Node* next; int value; ; void push(queue* q, int value) { Node* n = new Node; n->next = NULL; n->value = value; struct Queue { Node* head; Node* tail; Node* reclaim; ; void init(queue* q) { q->head = q->tail = q->reclaim = new Node; q->tail->next = n; q->tail = q->tail->next; while (q->reclaim!= q->head) { Node* tmp = q->reclaim; q->reclaim = q->reclaim->next; delete tmp; // returns false if queue is empty bool pop(queue* q, int* value) { if (q->head!= q->tail) { *value = q->head->next->value; q->head = q->head->next; return true; return false;

3 10 3 10 3 10 3 10 10 5

struct Node { Node* next; int value; ; struct Stack { Node* top; ; void init(stack* s) { s->top = NULL; void push(stack* s, Node* n) { while (1) { Node* old_top = s->top; n->next = old_top; if (compare_and_swap(&s->top, old_top, n) == old_top) return; Node* pop(stack* s) { while (1) { Node* old_top = s->top; if (old_top == NULL) return NULL; Node* new_top = old_top->next; if (compare_and_swap(&s->top, old_top, new_top) == old_top) return old_top;

A B C top B C top D B C top A D B C top B C top

struct Node { Node* next; int value; ; struct Stack { Node* top; int pop_count; ; void init(stack* s) { s->top = NULL; void push(stack* s, Node* n) { while (1) { Node* old_top = s->top; n->next = old_top; if (compare_and_swap(&s->top, old_top, n) == old_top) return; Node* pop(stack* s) { while (1) { int pop_count = s->pop_count; Node* top = s->top; if (top == NULL) return NULL; Node* new_top = top->next; if (double_compare_and_swap(&s->top, top, new_top, &s->pop_count, pop_count, pop_count+1)) return top;

struct Node { Node* next; int value; ; struct Stack { Node* top; int pop_count; ; void init(stack* s) { s->top = NULL; void push(stack* s, int value) { Node* n = new Node; n->value = value; while (1) { Node* old_top = s->top; n->next = old_top; if (compare_and_swap(&s->top, old_top, n) == old_top) return; int pop(stack* s) { while (1) { Stack old; old.pop_count = s->pop_count; old.top = s->top; if (old.top == NULL) return NULL; Stack new_stack; new_stack.top = old.top->next; new_stack.pop_count = old.pop_count+1; if (doubleword_compare_and_swap(&s, &old, new_stack)) int value = top->value; delete top; return value;

struct Node { Node* next; int value; ; struct Stack { Node* top; int pop_count; ; // per thread ptr (node that cannot // be deleted since the thread is // accessing it) Node* hazard; // per-thread list of nodes thread // must delete Node* retirelist; int retirelistsize; // delete nodes if possible void retire(node* ptr) { push(retirelist, ptr); retirelistsize++; if (retirelistsize > THRESHOLD) for (each node n in retirelist) { if (n not pointed to by any thread s hazard pointer) { remove n from list delete n; void init(stack* s) { s->top = NULL; void push(stack* s, int value) { Node* n = new Node; n->value = value; while (1) { Node* old_top = s->top; n->next = old_top; if (compare_and_swap(&s->top, old_top, n) == old_top) return; int pop(stack* s) { while (1) { Stack old; old.pop_count = s->pop_count; old.top = s->top; if (old.top == NULL) return NULL; hazard = old.top; Stack new_stack; new_stack.top = old.top->next; new_stack.pop_count = old.pop_count+1; if (doubleword_compare_and_swap(&s, &old, new_stack)) { int value = old.top->value; retire(old.top); return value; hazard = NULL;

struct Node { int value; Node* next; ; struct List { Node* head; ; // insert new node after specified node void insert_after(list* list, Node* after, int value) { Node* n = new Node; n->value = value; // assume case of insert into empty list handled // here (keep code on slide simple for class discussion) Node* prev = list->head; while (prev->next) { if (prev == after) { while (1) { Node* old_next = prev->next; n->next = old_next; if (compare_and_swap(&prev->next, old_next, n) == old_next) return; prev = prev->next;

X A B C D E