Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 #include "include/vector.h"
0028 
0029 bool dal_vector_construct(
0030     struct vector *vector,
0031     struct dc_context *ctx,
0032     uint32_t capacity,
0033     uint32_t struct_size)
0034 {
0035     vector->container = NULL;
0036 
0037     if (!struct_size || !capacity) {
0038         /* Container must be non-zero size*/
0039         BREAK_TO_DEBUGGER();
0040         return false;
0041     }
0042 
0043     vector->container = kcalloc(capacity, struct_size, GFP_KERNEL);
0044     if (vector->container == NULL)
0045         return false;
0046     vector->capacity = capacity;
0047     vector->struct_size = struct_size;
0048     vector->count = 0;
0049     vector->ctx = ctx;
0050     return true;
0051 }
0052 
0053 static bool dal_vector_presized_costruct(
0054     struct vector *vector,
0055     struct dc_context *ctx,
0056     uint32_t count,
0057     void *initial_value,
0058     uint32_t struct_size)
0059 {
0060     uint32_t i;
0061 
0062     vector->container = NULL;
0063 
0064     if (!struct_size || !count) {
0065         /* Container must be non-zero size*/
0066         BREAK_TO_DEBUGGER();
0067         return false;
0068     }
0069 
0070     vector->container = kcalloc(count, struct_size, GFP_KERNEL);
0071 
0072     if (vector->container == NULL)
0073         return false;
0074 
0075     /* If caller didn't supply initial value then the default
0076      * of all zeros is expected, which is exactly what dal_alloc()
0077      * initialises the memory to. */
0078     if (NULL != initial_value) {
0079         for (i = 0; i < count; ++i)
0080             memmove(
0081                 vector->container + i * struct_size,
0082                 initial_value,
0083                 struct_size);
0084     }
0085 
0086     vector->capacity = count;
0087     vector->struct_size = struct_size;
0088     vector->count = count;
0089     return true;
0090 }
0091 
0092 struct vector *dal_vector_presized_create(
0093     struct dc_context *ctx,
0094     uint32_t size,
0095     void *initial_value,
0096     uint32_t struct_size)
0097 {
0098     struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
0099 
0100     if (vector == NULL)
0101         return NULL;
0102 
0103     if (dal_vector_presized_costruct(
0104         vector, ctx, size, initial_value, struct_size))
0105         return vector;
0106 
0107     BREAK_TO_DEBUGGER();
0108     kfree(vector);
0109     return NULL;
0110 }
0111 
0112 struct vector *dal_vector_create(
0113     struct dc_context *ctx,
0114     uint32_t capacity,
0115     uint32_t struct_size)
0116 {
0117     struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
0118 
0119     if (vector == NULL)
0120         return NULL;
0121 
0122     if (dal_vector_construct(vector, ctx, capacity, struct_size))
0123         return vector;
0124 
0125     BREAK_TO_DEBUGGER();
0126     kfree(vector);
0127     return NULL;
0128 }
0129 
0130 void dal_vector_destruct(
0131     struct vector *vector)
0132 {
0133     kfree(vector->container);
0134     vector->count = 0;
0135     vector->capacity = 0;
0136 }
0137 
0138 void dal_vector_destroy(
0139     struct vector **vector)
0140 {
0141     if (vector == NULL || *vector == NULL)
0142         return;
0143     dal_vector_destruct(*vector);
0144     kfree(*vector);
0145     *vector = NULL;
0146 }
0147 
0148 uint32_t dal_vector_get_count(
0149     const struct vector *vector)
0150 {
0151     return vector->count;
0152 }
0153 
0154 void *dal_vector_at_index(
0155     const struct vector *vector,
0156     uint32_t index)
0157 {
0158     if (vector->container == NULL || index >= vector->count)
0159         return NULL;
0160     return vector->container + (index * vector->struct_size);
0161 }
0162 
0163 bool dal_vector_remove_at_index(
0164     struct vector *vector,
0165     uint32_t index)
0166 {
0167     if (index >= vector->count)
0168         return false;
0169 
0170     if (index != vector->count - 1)
0171         memmove(
0172             vector->container + (index * vector->struct_size),
0173             vector->container + ((index + 1) * vector->struct_size),
0174             (vector->count - index - 1) * vector->struct_size);
0175     vector->count -= 1;
0176 
0177     return true;
0178 }
0179 
0180 void dal_vector_set_at_index(
0181     const struct vector *vector,
0182     const void *what,
0183     uint32_t index)
0184 {
0185     void *where = dal_vector_at_index(vector, index);
0186 
0187     if (!where) {
0188         BREAK_TO_DEBUGGER();
0189         return;
0190     }
0191     memmove(
0192         where,
0193         what,
0194         vector->struct_size);
0195 }
0196 
0197 static inline uint32_t calc_increased_capacity(
0198     uint32_t old_capacity)
0199 {
0200     return old_capacity * 2;
0201 }
0202 
0203 bool dal_vector_insert_at(
0204     struct vector *vector,
0205     const void *what,
0206     uint32_t position)
0207 {
0208     uint8_t *insert_address;
0209 
0210     if (vector->count == vector->capacity) {
0211         if (!dal_vector_reserve(
0212             vector,
0213             calc_increased_capacity(vector->capacity)))
0214             return false;
0215     }
0216 
0217     insert_address = vector->container + (vector->struct_size * position);
0218 
0219     if (vector->count && position < vector->count)
0220         memmove(
0221             insert_address + vector->struct_size,
0222             insert_address,
0223             vector->struct_size * (vector->count - position));
0224 
0225     memmove(
0226         insert_address,
0227         what,
0228         vector->struct_size);
0229 
0230     vector->count++;
0231 
0232     return true;
0233 }
0234 
0235 bool dal_vector_append(
0236     struct vector *vector,
0237     const void *item)
0238 {
0239     return dal_vector_insert_at(vector, item, vector->count);
0240 }
0241 
0242 struct vector *dal_vector_clone(
0243     const struct vector *vector)
0244 {
0245     struct vector *vec_cloned;
0246     uint32_t count;
0247 
0248     /* create new vector */
0249     count = dal_vector_get_count(vector);
0250 
0251     if (count == 0)
0252         /* when count is 0 we still want to create clone of the vector
0253          */
0254         vec_cloned = dal_vector_create(
0255             vector->ctx,
0256             vector->capacity,
0257             vector->struct_size);
0258     else
0259         /* Call "presized create" version, independently of how the
0260          * original vector was created.
0261          * The owner of original vector must know how to treat the new
0262          * vector - as "presized" or as "regular".
0263          * But from vector point of view it doesn't matter. */
0264         vec_cloned = dal_vector_presized_create(vector->ctx, count,
0265             NULL,/* no initial value */
0266             vector->struct_size);
0267 
0268     if (NULL == vec_cloned) {
0269         BREAK_TO_DEBUGGER();
0270         return NULL;
0271     }
0272 
0273     /* copy vector's data */
0274     memmove(vec_cloned->container, vector->container,
0275             vec_cloned->struct_size * vec_cloned->capacity);
0276 
0277     return vec_cloned;
0278 }
0279 
0280 uint32_t dal_vector_capacity(const struct vector *vector)
0281 {
0282     return vector->capacity;
0283 }
0284 
0285 bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
0286 {
0287     void *new_container;
0288 
0289     if (capacity <= vector->capacity)
0290         return true;
0291 
0292     new_container = krealloc(vector->container,
0293                  capacity * vector->struct_size, GFP_KERNEL);
0294 
0295     if (new_container) {
0296         vector->container = new_container;
0297         vector->capacity = capacity;
0298         return true;
0299     }
0300 
0301     return false;
0302 }
0303 
0304 void dal_vector_clear(struct vector *vector)
0305 {
0306     vector->count = 0;
0307 }