1/* 2 * Copyright (c) 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20/* 21 SubzonePartition.h 22 Subzone partitioning scheme. 23 Copyright (c) 2009-2011 Apple Inc. All rights reserved. 24 */ 25 26#ifndef __AUTO_SUBZONE_PARTITION__ 27#define __AUTO_SUBZONE_PARTITION__ 28 29#include "Admin.h" 30#include "Locks.h" 31 32namespace Auto { 33 34 // Forward declarations 35 36 //----- SubzonePartition -----// 37 38 class SubzonePartition { 39 enum { 40 kPartitionUnscanned = 1, 41 kPartitionRetained = 2, 42 kPartitionCount = 4 43 }; 44 45 Admin _small[kPartitionCount]; 46 Admin _medium[kPartitionCount]; 47 48 public: 49 void initialize(Zone *zone); 50 51 Admin &admin(const size_t size, const usword_t layout, bool refcount_is_one) { 52 usword_t partion = ((layout & AUTO_UNSCANNED) ? kPartitionUnscanned : 0) | (refcount_is_one ? kPartitionRetained : 0); 53 return (size < allocate_quantum_medium ? _small[partion] : _medium[partion]); 54 } 55 56 void lock() { 57 for (usword_t i = 0; i < kPartitionCount; ++i) { 58 spin_lock(_small[i].lock()); 59 spin_lock(_medium[i].lock()); 60 } 61 } 62 63 void unlock() { 64 for (usword_t i = kPartitionCount; i > 0; --i) { 65 spin_unlock(_medium[i - 1].lock()); 66 spin_unlock(_small[i - 1].lock()); 67 } 68 } 69 70 bool locked() { 71 for (usword_t i = 0; i < kPartitionCount; ++i) { 72 TrySpinLock smallAttempt(_small[i].lock()); 73 if (!smallAttempt) return true; 74 TrySpinLock mediumAttempt(_medium[i].lock()); 75 if (!mediumAttempt) return true; 76 } 77 return false; 78 } 79 80 // 81 // for_each 82 // 83 // Applies block to all partitioned admins. 84 // 85 void for_each(void (^block) (Admin &admin)) { 86 for (usword_t i = 0; i < kPartitionCount; ++i) { 87 block(_small[i]); 88 block(_medium[i]); 89 } 90 } 91 92 usword_t purge_free_space() { 93 usword_t bytes_purged = 0; 94 for (usword_t i = 0; i < kPartitionCount; ++i) { 95 bytes_purged += _small[i].purge_free_space(); 96 bytes_purged += _medium[i].purge_free_space(); 97 } 98 return bytes_purged; 99 } 100 101 usword_t purge_free_space_no_lock() { 102 usword_t bytes_purged = 0; 103 for (usword_t i = 0; i < kPartitionCount; ++i) { 104 bytes_purged += _small[i].purge_free_space_no_lock(); 105 bytes_purged += _medium[i].purge_free_space_no_lock(); 106 } 107 return bytes_purged; 108 } 109 110 class Lock { 111 SubzonePartition &_partition; 112 public: 113 Lock(SubzonePartition &partition) : _partition(partition) { _partition.lock(); } 114 ~Lock() { _partition.unlock(); } 115 }; 116 }; 117 118}; 119 120#endif /* __AUTO_SUBZONE_PARTITION__ */ 121